From 095dd3a5afa2af67bdda578a2b8bed358a3f3df8 Mon Sep 17 00:00:00 2001 From: Pavel Cisar Date: Thu, 11 Nov 2021 18:01:08 +0100 Subject: [PATCH] More python tests --- tests/bugs/core_1076_test.py | 31 +- tests/bugs/core_1148_test.py | 4 +- tests/bugs/core_1249_test.py | 33 +- tests/bugs/core_1263_test.py | 40 ++- tests/bugs/core_1286_test.py | 23 +- tests/bugs/core_1291_test.py | 677 ++++++++++++++++++++++++++++++++++- tests/bugs/core_1315_test.py | 21 +- tests/bugs/core_1347_test.py | 97 +++-- tests/bugs/core_1378_test.py | 113 ++++-- tests/bugs/core_1384_test.py | 46 ++- tests/bugs/core_1389_test.py | 81 +++-- tests/bugs/core_1431_test.py | 48 ++- tests/bugs/core_1506_test.py | 33 +- tests/bugs/core_1539_test.py | 116 ++++-- tests/bugs/core_1642_test.py | 73 ++-- tests/bugs/core_1725_test.py | 366 ++++++++++++++----- 16 files changed, 1417 insertions(+), 385 deletions(-) diff --git a/tests/bugs/core_1076_test.py b/tests/bugs/core_1076_test.py index daccb47e..b26db17f 100644 --- a/tests/bugs/core_1076_test.py +++ b/tests/bugs/core_1076_test.py @@ -15,7 +15,7 @@ # qmid: import pytest -from firebird.qa import db_factory, python_act, Action +from firebird.qa import db_factory, python_act, Action, user_factory, User # version: 3.0 # resources: None @@ -171,6 +171,9 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) act_1 = python_act('db_1', substitutions=substitutions_1) +user_1 = user_factory(name="Nebuchadnezzar2_King_of_Babylon", + password="Nebu_King_of_Babylon") + expected_stdout_1 = """ SEC$USER_NAME NEBUCHADNEZZAR2_KING_OF_BABYLON SEC$FIRST_NAME Nebuchadnezzar3_King_of_Babylon @@ -179,22 +182,16 @@ SEC$LAST_NAME Nebuchadnezzar5_King_of_Babylon """ @pytest.mark.version('>=3.0') -def test_1(act_1: Action): - with act_1.connect_server() as srv: - check_login = "Nebuchadnezzar2_King_of_Babylon" - srv.user.add(user_name=check_login, password="Nebu_King_of_Babylon") - srv.user.update(user_name=check_login, - first_name="Nebuchadnezzar3_King_of_Babylon", - middle_name="Nebuchadnezzar4_King_of_Babylon", - last_name="Nebuchadnezzar5_King_of_Babylon") - # - act_1.script = f"""set list on; +def test_1(act_1: Action, user_1: User): + user_1.update(first_name="Nebuchadnezzar3_King_of_Babylon", + middle_name="Nebuchadnezzar4_King_of_Babylon", + last_name="Nebuchadnezzar5_King_of_Babylon") + # + act_1.script = f"""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('{check_login}'); -commit; -drop user {check_login}; +where upper(sec$user_name) = upper('{user_1.name}'); """ - act_1.expected_stdout = expected_stdout_1 - act_1.execute() - assert act_1.clean_stdout == act_1.clean_expected_stdout + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_stdout == act_1.clean_expected_stdout diff --git a/tests/bugs/core_1148_test.py b/tests/bugs/core_1148_test.py index 053aeeae..9e78d758 100644 --- a/tests/bugs/core_1148_test.py +++ b/tests/bugs/core_1148_test.py @@ -17,7 +17,7 @@ # qmid: bugs.core_1148 import pytest -from firebird.qa import db_factory, python_act, Action, temp_user, User +from firebird.qa import db_factory, python_act, Action, user_factory, User from firebird.driver import DatabaseError # version: 2.5 @@ -95,7 +95,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) act_1 = python_act('db_1', substitutions=substitutions_1) -user_1 = temp_user(name='TMP$C1148', password='QweRtyUi') +user_1 = user_factory(name='TMP$C1148', password='QweRtyUi') @pytest.mark.version('>=2.5') def test_1(act_1: Action, user_1: User): diff --git a/tests/bugs/core_1249_test.py b/tests/bugs/core_1249_test.py index e4c71e20..4ec53c56 100644 --- a/tests/bugs/core_1249_test.py +++ b/tests/bugs/core_1249_test.py @@ -9,7 +9,8 @@ # qmid: bugs.core_1249 import pytest -from firebird.qa import db_factory, isql_act, Action +from firebird.qa import db_factory, python_act, Action +from firebird.driver import ShutdownMode, ShutdownMethod, DatabaseError # version: 2.0.2 # resources: None @@ -22,11 +23,11 @@ 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!') @@ -35,7 +36,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 @@ -46,21 +47,21 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # # 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. - """ +act_1 = python_act('db_1', substitutions=substitutions_1) @pytest.mark.version('>=2.0.2') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") - - +def test_1(act_1: Action): + with act_1.connect_server() as srv, act_1.db.connect() as con: + srv.database.shutdown(database=str(act_1.db.db_path), mode=ShutdownMode.FULL, + method=ShutdownMethod.FORCED, timeout=0) + c = con.cursor() + with pytest.raises(DatabaseError, match='.*shutdown'): + c.execute('select 1 from rdb$database') + # + srv.database.bring_online(database=str(act_1.db.db_path)) diff --git a/tests/bugs/core_1263_test.py b/tests/bugs/core_1263_test.py index 1e0b95d9..22147ec9 100644 --- a/tests/bugs/core_1263_test.py +++ b/tests/bugs/core_1263_test.py @@ -2,19 +2,19 @@ # # id: bugs.core_1263 # title: GSec incorrectly processes some switches -# decription: +# 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 +from firebird.qa import db_factory, python_act, Action # version: 3.0 # resources: None -substitutions_1 = [('^((?!invalid switch specified).)*$', ''), ('invalid switch specified.*', 'invalid switch specified'), ('.*gsec is deprecated.*', '')] +substitutions_1 = [] init_script_1 = """""" @@ -32,20 +32,32 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # """ # runProgram('gsec',['-user',user_name,'-pas',user_password],commands) #--- -#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +act_1 = python_act('db_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 - """ +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 +error in switch specifications +GSEC> +""" @pytest.mark.version('>=3.0') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + 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 +""" + act_1.expected_stderr = expected_stderr_1 + act_1.gsec(input=commands) + assert act_1.clean_expected_stderr == act_1.clean_stderr diff --git a/tests/bugs/core_1286_test.py b/tests/bugs/core_1286_test.py index de91e12c..b37d8642 100644 --- a/tests/bugs/core_1286_test.py +++ b/tests/bugs/core_1286_test.py @@ -2,14 +2,14 @@ # # id: bugs.core_1286 # title: isql: zero divide + coredump when use "-pag 0" command switch & set heading on inside .sql script -# decription: +# 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 +from firebird.qa import db_factory, python_act, Action # version: 2.5.2 # resources: None @@ -31,9 +31,10 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # -- 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """ R @@ -41,9 +42,17 @@ expected_stdout_1 = """ 1 """ +test_script_1 = """ +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 +""" + @pytest.mark.version('>=2.5.2') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.isql(switches=['-pag', '0'], input=test_script_1) + assert act_1.clean_expected_stdout == act_1.clean_stdout diff --git a/tests/bugs/core_1291_test.py b/tests/bugs/core_1291_test.py index 650493b8..7ec8e3c4 100644 --- a/tests/bugs/core_1291_test.py +++ b/tests/bugs/core_1291_test.py @@ -2,43 +2,692 @@ # # 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: +# 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 +from firebird.qa import db_factory, python_act, Action # version: 2.1 # resources: None -substitutions_1 = [('Use CONNECT or CREATE DATABASE to specify a database', ''), ('SQL> ', ''), ('CON> ', '')] +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 = """ +SET SQL DIALECT 3; +SET NAMES WIN1251; +CREATE DATABASE '%s' DEFAULT CHARACTER SET WIN1251; + +CREATE DOMAIN DMN_BOOL AS +SMALLINT +DEFAULT 0; + +CREATE DOMAIN DMN_PRICE AS +DOUBLE PRECISION +DEFAULT 0 +CHECK (Value >= 0); + +CREATE DOMAIN DMN_DOCNAME AS +VARCHAR(20) CHARACTER SET WIN1251; + +CREATE TABLE TBL_CONST_FLOAT ( + NAME VARCHAR(20) CHARACTER SET WIN1251 NOT NULL, + VAL DOUBLE PRECISION, + COMMENT VARCHAR(128) CHARACTER SET WIN1251 +); + +CREATE TABLE TBL_EXPORTENTRY ( + ID_EXPORTGROUPENTRY INTEGER NOT NULL, + ID_EXPORTFIELDDOC INTEGER NOT NULL, + ACCOUNTCREDIT INTEGER DEFAULT 0 NOT NULL, + ACCOUNTDEBIT INTEGER DEFAULT 0 NOT NULL +); + +CREATE TABLE TBL_INDOC_TEMP ( + ID_INDOC_TEMP INTEGER NOT NULL, + ID_POINT INTEGER NOT NULL, + ID_ITEM INTEGER NOT NULL, + ID_INDOC INTEGER NOT NULL, + SERNO VARCHAR(20) CHARACTER SET WIN1251, + POINTMUL DOUBLE PRECISION NOT NULL, + VOLUME DMN_PRICE NOT NULL /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICEDOC DMN_PRICE /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICERUB DMN_PRICE /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICECUR DMN_PRICE /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICECALCDOC DMN_PRICE NOT NULL /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICECALCRUB DMN_PRICE NOT NULL /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + PRICECALCCUR DMN_PRICE NOT NULL /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + NDS DMN_PRICE /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + F_CANSALE DMN_BOOL NOT NULL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + PASPORT VARCHAR(64) CHARACTER SET WIN1251, + PASPORTCREATEDATE TIMESTAMP, + PASPORTEXPIREDATE TIMESTAMP, + REGISTRATION VARCHAR(64) CHARACTER SET WIN1251, + PROTOCOL VARCHAR(64) CHARACTER SET WIN1251, + SERTIFICAT VARCHAR(128) CHARACTER SET WIN1251, + ID_CERTCENTER INTEGER DEFAULT 0, + ITEMCREATEDATE TIMESTAMP, + ITEMEXPIREDATE TIMESTAMP, + ID_PARENT_OUTDOC_TEMP INTEGER DEFAULT 0, + SUMMDOC COMPUTED BY (Volume*PriceDoc), + SUMMRUB COMPUTED BY (Volume*PriceRub), + SUMMCUR COMPUTED BY (Volume*PriceCur), + SUMMCALCDOC COMPUTED BY (Volume*PriceCalcDoc), + SUMMCALCRUB COMPUTED BY (Volume*PriceCalcRub), + SUMMCALCCUR COMPUTED BY (Volume*PriceCalcCur), + SUMMNDSDOC COMPUTED BY (NDS*SummCalcDoc/100), + SUMMNDSRUB COMPUTED BY (NDS*SummCalcRub/100), + SUMMNDSCUR COMPUTED BY (NDS*SummCalcCur/100), + SUMMWITHNDSDOC COMPUTED BY (SummCalcDoc+SummNDSDoc), + SUMMWITHNDSRUB COMPUTED BY (SummCalcRub+SummNDSRub), + SUMMWITHNDSCUR COMPUTED BY (SummCalcCur+SummNDSCur), + PRICEDOC_IN DOUBLE PRECISION DEFAULT 0, + EXPIREPERCENT COMPUTED BY (Cast(100 * (ItemExpireDate - CURRENT_TIMESTAMP) / (ItemExpireDate - ItemCreateDate) as Integer)) +); + +CREATE TABLE TBL_OUTDOC_TEMP ( + ID_OUTDOC_TEMP INTEGER NOT NULL, + ID_OUTDOC INTEGER NOT NULL, + ID_ITEMSALE INTEGER, + ID_ITEM INTEGER, + ID_POINT INTEGER NOT NULL, + VOLUME DOUBLE PRECISION DEFAULT 0 NOT NULL, + PRICEDOC DOUBLE PRECISION DEFAULT 0 NOT NULL, + NDS DOUBLE PRECISION DEFAULT 0 NOT NULL, + BUILDERPERCENT DOUBLE PRECISION DEFAULT 0 NOT NULL, + SUMMDOC DOUBLE PRECISION DEFAULT 0, + SUMMNDSDOC DOUBLE PRECISION DEFAULT 0, + SUMMWITHNDSDOC DOUBLE PRECISION DEFAULT 0, + BUILDERPRICE COMPUTED BY (PriceDoc*100/(100+BuilderPercent)) +); + +CREATE TABLE TBL_ITEMSALE ( + ID_ITEMSALE INTEGER NOT NULL, + ID_STORE INTEGER NOT NULL, + ID_ITEM INTEGER NOT NULL, + ID_FIRSTINDOC_TEMP INTEGER NOT NULL, + F_ALOWSALE DMN_BOOL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + VOLUME DMN_PRICE NOT NULL /* DMN_PRICE = DOUBLE PRECISION DEFAULT 0 CHECK (Value >= 0) */, + SALEPRICERUB DOUBLE PRECISION DEFAULT 0 NOT NULL, + SALEPRICECUR DOUBLE PRECISION DEFAULT 0 NOT NULL, + F_IMPORTED DMN_BOOL NOT NULL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + V_VOLUME DOUBLE PRECISION DEFAULT 0, + V_MASS DOUBLE PRECISION DEFAULT 0 +); + +CREATE TABLE TBL_INDOC ( + ID_INDOC INTEGER NOT NULL, + ID_STORE INTEGER NOT NULL, + ID_FIRM INTEGER NOT NULL, + ID_SELFFIRM INTEGER NOT NULL, + ID_CUR INTEGER NOT NULL, + DOCTYPE INTEGER NOT NULL, + DOCNAME DMN_DOCNAME /* DMN_DOCNAME = VARCHAR(20) */, + DATECREATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + DATEDOC TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + DATELASTEDIT TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + DATESTORE TIMESTAMP, + ID_USERCREATE INTEGER NOT NULL, + ID_USERLOCK INTEGER, + F_FINISHED DMN_BOOL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + F_STORE DMN_BOOL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + F_SPECIAL DMN_BOOL /* DMN_BOOL = SMALLINT DEFAULT 0 */, + ADDENDUM VARCHAR(128) CHARACTER SET WIN1251, + COMMENT VARCHAR(128) CHARACTER SET WIN1251, + COURSE DOUBLE PRECISION NOT NULL, + ID_PARENT_OUTDOC INTEGER DEFAULT 0 NOT NULL, + PRICEDOC_IN_IMPORTED SMALLINT DEFAULT 0 NOT NULL +); + +SET TERM ^ ; + +CREATE PROCEDURE PRC_EXPSUMM_8_10 ( + ID_EXPORTFIELDDOC INTEGER, + ID_OUTDOC INTEGER, + NDSDIV DOUBLE PRECISION) +RETURNS ( + SUMMRUS DOUBLE PRECISION, + SUMMDOC DOUBLE PRECISION) +AS +begin + IF (id_exportfielddoc=130) 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 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=131) 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 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=132) 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 and a.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=133) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=134) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=135) 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 and a.nds>0 and a.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=136) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=137) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=138) 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 and a.nds>0 and a.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=139) 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 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=140) 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 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=141) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=142) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=143) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=144) 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 and b.nds>0 and b.nds<:NDSDiv + INTO :summrus, :summdoc; + END + SUSPEND; +END +^ + +CREATE PROCEDURE PRC_EXPSUMM_8_20 ( + ID_EXPORTFIELDDOC INTEGER, + ID_OUTDOC INTEGER, + NDSDIV DOUBLE PRECISION) +RETURNS ( + SUMMRUS DOUBLE PRECISION, + SUMMDOC DOUBLE PRECISION) +AS +begin + IF (id_exportfielddoc=145) 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 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=146) 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 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=147) 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 and a.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=148) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=149) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=150) 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 and a.nds>0 and a.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=151) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=152) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=153) 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 and a.nds>0 and a.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=154) 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 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=155) 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 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=156) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=157) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=158) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + IF (id_exportfielddoc=159) 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 and b.nds>0 and b.nds>=:NDSDiv + INTO :summrus, :summdoc; + END + SUSPEND; +END +^ + +CREATE PROCEDURE PRC_EXPSUMM_8( + ID_INDOC INTEGER, + ID_OUTDOC INTEGER, + ID_GROUP INTEGER) +RETURNS ( + ACCOUNTCREDIT INTEGER, + ACCOUNTDEBIT INTEGER, + SUMMRUS DOUBLE PRECISION, + SUMMDOC DOUBLE PRECISION) +AS +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 +^ + +SET TERM ; ^ + +COMMIT WORK; + +SHOW PROCEDURE PRC_EXPSUMM_8; + +EXIT; +""" + +db_1 = db_factory(do_not_create=True) # 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """Procedure text: ============================================================================= @@ -256,8 +905,10 @@ SUMMDOC OUTPUT DOUBLE PRECISION """ @pytest.mark.version('>=2.1') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.isql(switches=['-user', act_1.db.user, '-password', act_1.db.password], + input=test_script_1 % act_1.db.dsn, connect_db=False, charset='WIN1251') + assert act_1.clean_expected_stdout == act_1.clean_stdout diff --git a/tests/bugs/core_1315_test.py b/tests/bugs/core_1315_test.py index bb6dd35d..29a46655 100644 --- a/tests/bugs/core_1315_test.py +++ b/tests/bugs/core_1315_test.py @@ -2,14 +2,14 @@ # # id: bugs.core_1315 # title: Data type unknown -# decription: +# 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 +from firebird.qa import db_factory, python_act, Action # version: 2.1 # resources: None @@ -34,7 +34,8 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # cur.execute(statement,[None]) # printData(cur) #--- -#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """COALESCE ----------- @@ -46,8 +47,16 @@ COALESCE """ @pytest.mark.version('>=2.1') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action, capsys): + with act_1.db.connect() as con: + c = con.cursor() + statement = c.prepare('select coalesce(?,1) from RDB$DATABASE') + c.execute(statement,[2]) + act_1.print_data(c) + c.execute(statement,[None]) + act_1.print_data(c) + act_1.stdout = capsys.readouterr().out + act_1.expected_stdout = expected_stdout_1 + assert act_1.clean_stdout == act_1.clean_expected_stdout diff --git a/tests/bugs/core_1347_test.py b/tests/bugs/core_1347_test.py index f88becaa..39a0ffa0 100644 --- a/tests/bugs/core_1347_test.py +++ b/tests/bugs/core_1347_test.py @@ -2,7 +2,7 @@ # # id: bugs.core_1347 # title: Unexpected "cannot transliterate" error -# decription: +# 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). @@ -12,14 +12,15 @@ # 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 +from firebird.qa import db_factory, python_act, Action, temp_file +from pathlib import Path # version: 2.5 # resources: None @@ -32,31 +33,31 @@ 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 )): @@ -67,16 +68,16 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # 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) , @@ -98,52 +99,90 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """ RDB$PROCEDURE_NAME SP_TEST - Records affected: 1 + Records affected: 1 """ +tmp_file_1 = temp_file('non_ascii_ddl.sql') + +sql_txt = '''set bail on; + +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'); +''' + @pytest.mark.version('>=2.5') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action, tmp_file_1: Path): + tmp_file_1.write_bytes(sql_txt.encode('cp1251')) + act_1.expected_stdout = expected_stdout_1 + act_1.isql(switches=['-q'], input_file=tmp_file_1, charset='win1251', io_enc='cp1251') + assert act_1.clean_expected_stdout == act_1.clean_stdout diff --git a/tests/bugs/core_1378_test.py b/tests/bugs/core_1378_test.py index 18631ffe..59b7984a 100644 --- a/tests/bugs/core_1378_test.py +++ b/tests/bugs/core_1378_test.py @@ -2,7 +2,7 @@ # # id: bugs.core_1378 # title: Domain names and charset issues -# decription: +# 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). @@ -12,14 +12,15 @@ # 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: +# +# 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 +from firebird.qa import db_factory, python_act, Action, temp_file +from pathlib import Path # version: 2.5.9 # resources: None @@ -32,31 +33,31 @@ 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 )): @@ -67,16 +68,16 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # 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; @@ -92,13 +93,13 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # ^ # 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 @@ -118,36 +119,84 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) + +tmp_file_1 = temp_file('non_ascii_ddl.sql') + +sql_txt = ''' +set bail on; + +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'); +''' expected_stdout_1 = """ RDB$PROCEDURE_NAME SP_TEST @@ -174,8 +223,10 @@ expected_stdout_1 = """ """ @pytest.mark.version('>=2.5.9') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action, tmp_file_1: Path): + tmp_file_1.write_bytes(sql_txt.encode('cp1251')) + act_1.expected_stdout = expected_stdout_1 + act_1.isql(switches=['-q'], input_file=tmp_file_1, charset='win1251', io_enc='cp1251') + assert act_1.clean_expected_stdout == act_1.clean_stdout diff --git a/tests/bugs/core_1384_test.py b/tests/bugs/core_1384_test.py index e0cefc23..5a249a50 100644 --- a/tests/bugs/core_1384_test.py +++ b/tests/bugs/core_1384_test.py @@ -2,20 +2,20 @@ # # id: bugs.core_1384 # title: LIKE doesn't work correctly with collations using SPECIALS-FIRST=1 -# decription: +# 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. +# Script that must be executed by ISQL does NOT contain any non-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 @@ -33,25 +33,25 @@ 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 + 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 + 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) +db_1 = db_factory(charset='UTF8', 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'; @@ -59,12 +59,19 @@ db_1 = db_factory(charset='ISO8859_1', sql_dialect=3, init=init_script_1) # 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) + +test_script_1 = """ +set list on; +show collation; +select * from v_test; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1, charset='ISO8859_1') expected_stdout_1 = """ COLL_ES, CHARACTER SET ISO8859_1, FROM EXTERNAL ('ES_ES_CI_AI'), 'SPECIALS-FIRST=1' @@ -76,8 +83,9 @@ expected_stdout_1 = """ """ @pytest.mark.version('>=2.1.7') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_stdout == act_1.clean_expected_stdout diff --git a/tests/bugs/core_1389_test.py b/tests/bugs/core_1389_test.py index 8a79163b..371d7a44 100644 --- a/tests/bugs/core_1389_test.py +++ b/tests/bugs/core_1389_test.py @@ -2,35 +2,36 @@ # # id: bugs.core_1389 # title: Indexed MIN/MAX aggregates produce three index reads instead of the expected one indexed read -# decription: +# 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): +# 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 x from ... order by x asc rows 1; # * select min(y) from ...; -# * select y from ... order by y desc rows 1; -# +# * 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 +from firebird.qa import db_factory, python_act, Action +from firebird.driver import DbInfoCode # version: 2.5 # resources: None @@ -55,27 +56,27 @@ db_1 = db_factory(sql_dialect=3, init=init_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', +# +# 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' +# '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(): @@ -83,20 +84,36 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 - """ +act_1 = python_act('db_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_1(db_1): - pytest.fail("Test not IMPLEMENTED") - - +def test_1(act_1: Action, capsys): + with act_1.db.connect() as con: + c = con.cursor() + c.execute("select rdb$relation_id from rdb$relations where trim(rdb$relation_name)=upper('test')") + test_rel = c.fetchone()[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'] + previous_idx_counter = 0 + for cmd in sql_set: + c.execute(cmd).fetchone() + counts = con.info.get_info(DbInfoCode.READ_IDX_COUNT) + for k, cumulative_idx_counter in counts.items(): + if k == test_rel: + print('Number of indexed reads:', cumulative_idx_counter - previous_idx_counter) + previous_idx_counter = cumulative_idx_counter + # + output = capsys.readouterr() + assert output.out == expected_stdout_1 diff --git a/tests/bugs/core_1431_test.py b/tests/bugs/core_1431_test.py index 9cd8b71e..2c310ed0 100644 --- a/tests/bugs/core_1431_test.py +++ b/tests/bugs/core_1431_test.py @@ -2,29 +2,29 @@ # # id: bugs.core_1431 # title: Greek characters in cp1251 vs uppercasing -# decription: +# 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: +# qmid: import pytest from firebird.qa import db_factory, isql_act, Action @@ -84,7 +84,7 @@ init_script_1 = """ 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'); @@ -172,14 +172,14 @@ init_script_1 = """ commit; """ -db_1 = db_factory(sql_dialect=3, init=init_script_1) +db_1 = db_factory(sql_dialect=3, init=init_script_1, charset='UTF8') # test_script_1 #--- -# -# +# +# # db_conn.close() -# +# # sql_cmd=''' # set names WIN1251; # connect '%(dsn)s' user '%(user_name)s' password '%(user_password)s'; @@ -192,12 +192,23 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # having count(*) <> 2 # ; # ''' % dict(globals(), **locals()) -# +# # runProgram( 'isql', [ '-q' ], sql_cmd) -# -# +# +# #--- -#act_1 = python_act('db_1', test_script_1, substitutions=substitutions_1) + +test_script_1 = """ +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 ; +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1, charset='WIN1251') expected_stdout_1 = """ HAS_NO_UPPER_CASE_EQUIV LOW 9 SINGLE QUOTE @@ -234,8 +245,9 @@ expected_stdout_1 = """ """ @pytest.mark.version('>=2.1.7') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_stdout == act_1.clean_expected_stdout diff --git a/tests/bugs/core_1506_test.py b/tests/bugs/core_1506_test.py index 151c3689..2b3bfd29 100644 --- a/tests/bugs/core_1506_test.py +++ b/tests/bugs/core_1506_test.py @@ -2,35 +2,36 @@ # # id: bugs.core_1506 # title: Server crash with isc_dsql_execute_immediate and zero length string -# decription: +# 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. +# +# 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 +from firebird.qa import db_factory, python_act, Action +from firebird.driver import DatabaseError # version: 2.5 # resources: None @@ -43,14 +44,15 @@ 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """ Error while executing SQL statement: @@ -59,8 +61,9 @@ expected_stdout_1 = """ """ @pytest.mark.version('>=2.5') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + with act_1.db.connect() as con: + with pytest.raises(DatabaseError, match='.*-Unexpected end of command.*'): + con.execute_immediate('') diff --git a/tests/bugs/core_1539_test.py b/tests/bugs/core_1539_test.py index d89a24c3..fe9b8edb 100644 --- a/tests/bugs/core_1539_test.py +++ b/tests/bugs/core_1539_test.py @@ -2,7 +2,7 @@ # # id: bugs.core_1539 # title: select * from rdb$triggers where rdb$trigger_source like 'CHECK%' -# decription: +# 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 @@ -19,19 +19,19 @@ # 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 @@ -43,7 +43,7 @@ from firebird.qa import db_factory, isql_act, Action # version: 2.1 # resources: None -substitutions_1 = [] +substitutions_1 = [('RDB$TRIGGER_SOURCE.*', 'RDB$TRIGGER_SOURCE ')] init_script_1 = """ -- ### ONCE AGAIN ### @@ -56,7 +56,7 @@ init_script_1 = """ fixerkey int, decisiondate date ); - + alter table test add constraint test_bugtype check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) ,add constraint test_bugfrequency check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) @@ -66,35 +66,35 @@ init_script_1 = """ commit; """ -db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=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 # 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 +# # 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 )): @@ -105,13 +105,13 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # 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'; @@ -121,39 +121,87 @@ db_1 = db_factory(charset='WIN1251', sql_dialect=3, init=init_script_1) # -- 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 +# 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) +test_script_1 = """ +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); +""" + +act_1 = isql_act('db_1', test_script_1, substitutions=substitutions_1, charset='WIN1251') + +expected_stdout_1 = """ + +RDB$TRIGGER_NAME CHECK_1 +RDB$TRIGGER_SOURCE 0:b +check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) + +RDB$TRIGGER_NAME CHECK_2 +RDB$TRIGGER_SOURCE 0:e +check (bugtype in ('зрабіць', 'трэба зрабіць', 'недахоп', 'памылка', 'катастрофа')) + +RDB$TRIGGER_NAME CHECK_3 +RDB$TRIGGER_SOURCE 0:11 +check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) + +RDB$TRIGGER_NAME CHECK_4 +RDB$TRIGGER_SOURCE 0:14 +check (bugfrequency in ('ніколі', 'зрэдку', 'часам', 'часта', 'заўсёды', 'не прыкладаецца')) + +RDB$TRIGGER_NAME CHECK_5 +RDB$TRIGGER_SOURCE 0:17 +check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) + +RDB$TRIGGER_NAME CHECK_6 +RDB$TRIGGER_SOURCE 0:1a +check (decision in ('адкрыта', 'зроблена', 'састарэла', 'адхілена', 'часткова', 'выдалена')) + +RDB$TRIGGER_NAME CHECK_7 +RDB$TRIGGER_SOURCE 0:1d +check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) + +RDB$TRIGGER_NAME CHECK_8 +RDB$TRIGGER_SOURCE 0:20 +check ((decision = 'адкрыта' and fixerkey is null and decisiondate is null) or (decision <> 'адкрыта' and not fixerkey is null and not decisiondate is null)) +""" @pytest.mark.version('>=2.1') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action): + act_1.expected_stdout = expected_stdout_1 + act_1.execute() + assert act_1.clean_stdout == act_1.clean_expected_stdout diff --git a/tests/bugs/core_1642_test.py b/tests/bugs/core_1642_test.py index 332a23a2..45c89b68 100644 --- a/tests/bugs/core_1642_test.py +++ b/tests/bugs/core_1642_test.py @@ -2,18 +2,18 @@ # # 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, +# 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 +from firebird.qa import db_factory, python_act, Action, user_factory, User # version: 2.5 # resources: None @@ -21,33 +21,7 @@ from firebird.qa import db_factory, isql_act, Action 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 + 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; @@ -60,38 +34,39 @@ 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) + +act_1 = python_act('db_1', substitutions=substitutions_1) expected_stdout_1 = """ TMP$C1642_ALAN OK. @@ -99,9 +74,23 @@ expected_stdout_1 = """ TMP$C1642_MICK OK. """ +user_1 = user_factory(name='tmp$c1642_alan', password='123') +user_2 = user_factory(name='tmp$c1642_john', password = '456') +user_3 = user_factory(name='tmp$c1642_mick', password = '789') + @pytest.mark.version('>=2.5') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") +def test_1(act_1: Action, user_1: User, user_2: User, user_3: User, capsys): + act_1.expected_stdout = expected_stdout_1 + for user in [user_1, user_2, user_3]: + with act_1.db.connect(user=user.name, password=user.password) as con: + c = con.cursor() + c.execute('select who_am_i, my_attach_id from v_my_attach') + for row in c: + print(row[0], row[1]) + act_1.stdout = capsys.readouterr().out + assert act_1.clean_stdout == act_1.clean_expected_stdout + + + diff --git a/tests/bugs/core_1725_test.py b/tests/bugs/core_1725_test.py index fcc03114..844431ac 100644 --- a/tests/bugs/core_1725_test.py +++ b/tests/bugs/core_1725_test.py @@ -2,51 +2,212 @@ # # id: bugs.core_1725 # title: Unable to restore a database with inactive indices if any SP/trigger contains an explicit plan -# decription: +# 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 +from firebird.qa import db_factory, python_act, Action +from firebird.driver import SrvRestoreFlag, SrvRepairFlag +from io import BytesIO +from difflib import unified_diff # version: 3.0.6 # resources: None substitutions_1 = [('[ \t]+', ' ')] -init_script_1 = """""" +init_script_1 = """ +set bail on; + +create or alter procedure sp_init as begin end; +create or alter procedure sp_main as begin end; +create or alter procedure sp_worker as begin end; + +create or alter function fn_init returns int as begin end; +create or alter function fn_main returns int as begin end; +create or alter function fn_worker returns int as begin end; + + +create table test(id int primary key, x int, y int); +create index test_x on test(x); +create descending index test_y on test(y); +commit; + +insert into test(id, x, y) select row_number()over(), rand()*5, rand()*100 from rdb$types; +commit; + +create or alter view v_init as + select count(*) as cnt from test group by x + rows 1 +; + +create or alter view v_worker as + select count(*) as cnt + from test + group by y + plan (TEST ORDER TEST_Y) + union all + select cnt from v_init +; +commit; + + +set term ^; +execute block as +begin + rdb$set_context('USER_SESSION','INITIAL_DDL', '1'); +end +^ + +create or alter procedure sp_init as + declare c int; +begin + select count(*) from test group by x + rows 1 + into c + ; +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; +""" db_1 = db_factory(sql_dialect=3, init=init_script_1) # test_script_1 #--- -# +# # import os # import time # import shutil @@ -55,39 +216,39 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 +# # 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", @@ -96,59 +257,59 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 +# 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 @@ -158,19 +319,19 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # ; # end # ^ -# +# # create or alter procedure sp_main as # begin # execute procedure sp_worker; # end # ^ -# +# # create or alter procedure sp_worker as # declare c int; # begin # select sum(cnt) # from ( -# select count(*) as cnt +# select count(*) as cnt # from test group by x # plan (TEST ORDER TEST_X) # union all @@ -190,7 +351,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # return ( # select sum(cnt) # from ( -# select count(*) as cnt +# select count(*) as cnt # from test group by x # plan (TEST ORDER TEST_X) # union all @@ -204,7 +365,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # return fn_worker(); # end # ^ -# +# # create or alter package pg_test as # begin # function pg_fn_worker returns int; @@ -218,7 +379,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # return ( # select sum(cnt) # from ( -# select count(*) as cnt +# select count(*) as cnt # from test group by x # plan (TEST ORDER TEST_X) # union all @@ -226,13 +387,13 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # ) # ); # end -# +# # procedure pg_sp_worker as # declare c int; # begin # select sum(cnt) # from ( -# select count(*) as cnt +# select count(*) as cnt # from test group by x # plan (TEST ORDER TEST_X) # union all @@ -241,10 +402,10 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # into c # ; # end -# +# # end # ^ -# +# # create or alter trigger trg_attach active on connect position 0 as # declare c int; # begin @@ -252,7 +413,7 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # begin # select sum(cnt) # from ( -# select count(*) as cnt +# select count(*) as cnt # from test group by x # plan (TEST ORDER TEST_X) # union all @@ -265,27 +426,27 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 @@ -293,75 +454,75 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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(), +# 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(), +# 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. @@ -370,35 +531,60 @@ db_1 = db_factory(sql_dialect=3, init=init_script_1) # 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 +# +# # 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 - """ +act_1 = python_act('db_1', substitutions=substitutions_1) @pytest.mark.version('>=3.0.6') -@pytest.mark.xfail -def test_1(db_1): - pytest.fail("Test not IMPLEMENTED") - - +def test_1(act_1: Action): + # Extract metadata from initial DB + act_1.isql(switches=['-nod', '-x']) + meta_1 = act_1.stdout + act_1.reset() + # backup + restore _WITHOUT_ building indices: + backup = BytesIO() + with act_1.connect_server() as srv: + srv.database.local_backup(database=str(act_1.db.db_path), backup_stream=backup) + backup.seek(0) + srv.database.local_restore(backup_stream=backup, database=str(act_1.db.db_path), + flags=SrvRestoreFlag.DEACTIVATE_IDX | SrvRestoreFlag.REPLACE) + # Get FB log before validation, run validation and get FB log after it: + srv.info.get_log() + log_before = srv.readlines() + srv.database.repair(database=str(act_1.db.db_path), flags=SrvRepairFlag.CORRUPTION_CHECK) + srv.info.get_log() + log_after = srv.readlines() + # Extract metadata from restored DB + act_1.isql(switches=['-nod', '-x']) + meta_2 = act_1.stdout + act_1.reset() + # Restore with indices. This is necessary to drop the database safely otherwise connect + # to drop will fail in test treadown as connect trigger referes to index tat was not activated + with act_1.connect_server() as srv: + backup.seek(0) + srv.database.local_restore(backup_stream=backup, database=str(act_1.db.db_path), + flags=SrvRestoreFlag.REPLACE) + # + diff_meta = ''.join(unified_diff(meta_1.splitlines(), meta_2.splitlines())) + diff_log = [line for line in unified_diff(log_before, log_after) if line.startswith('+') and 'Validation finished:' in line] + # Checks + assert diff_meta == '' + assert diff_log == ['+\tValidation finished: 0 errors, 0 warnings, 0 fixed\n']