#coding:utf-8 """ ID: issue-7846 ISSUE: https://github.com/FirebirdSQL/firebird/issues/7846 TITLE: FB4 can't backup/restore int128-array DESCRIPTION: Test checks ability to make b/r of DB with table that has array-based columns of following types: smallint; integer; bigint; int128; double. NOTES: [16.09.2024] pzotov 1. Confirmed problem with b/r for INT128 on 4.0.4.3021 (dob: 17-nov-2023). Got after restore: [Decimal('0'), Decimal('0')] (although no errors were during insert origin data). Expected values: [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')]. Confirmed fix on 4.0.4.3022 (dob: 19-nov-2023). 2. Fix for #8100 ("The isc_array_lookup_bounds function returns invalid values...") required in order this test can pass on FB 5.x and 6.x. See commits (07-may-2024): * 5.x: https://github.com/FirebirdSQL/firebird/commit/26ca064202169c0558359fc9ab06b70e827466f0 * 6.x: https://github.com/FirebirdSQL/firebird/commit/17b007d14f8ccc6cfba0d63a3b2f21622ced20d0 FB 4.x was not affected by that bug. 3. INT128 type requires as argument only INTEGER values (from scope -2**127 ... +2**127-1) but NOT decimals. Rather, NUMERIC / DECIMAL columns allows only Decimal instances. (letter from Alex, 20.08.2024 16:11, subj: "gh-6544 ("Error writing an array of NUMERIC(24,6)" ) <...>" 4. DECFLOAT type had a problem in firebird-driver, fixed in v 1.10.5 (26-JUL-2024) 5. Some features must be implemented in engine and/or in firebird-driver for proper support of NUMERIC datatype which have big values and use int128 as underlying storage. Discussed with pcisar, see subj "firebird-driver and its support for FB datatypes", letters since 21-jul-2024. See also: https://github.com/FirebirdSQL/firebird/issues/6544#issuecomment-2294778138 Checked on 6.0.0.457; 5.0.2.1499; 4.0.5.3136. """ import pytest from firebird.qa import * from io import BytesIO from firebird.driver import SrvRestoreFlag, DatabaseError, InterfaceError from decimal import Decimal import traceback import time init_script = """ recreate table test_arr( id int generated by default as identity constraint test_pk primary key ,v_smallint smallint[2] ,v_integer int[2] ,v_bigint bigint[2] ,v_int128 int128[2] ,v_double double precision[2] ,v_decfloat decfloat[2] ); """ db = db_factory(init = init_script) act = python_act('db') #-------------------------------------- def try_insert(con, cur, fld, data): print(f'\nTrying to add array in {fld}') try: print(f'Data: {data}') with cur.prepare(f"insert into test_arr({fld}) values (?)") as ps: for x in data: cur.execute(ps, (x,)) cur.execute(f'select {fld} from test_arr order by id desc rows 1') for r in cur: for x in r[0]: print(x, type(x)) con.commit() print('Success.') #except (ValueError, InterfaceError, DatabaseError) as e: except Exception as e: for x in traceback.format_exc().split('\n'): print(' ',x) #-------------------------------------- @pytest.mark.version('>=4.0.5') def test_1(act: Action, capsys): with act.db.connect() as con: cur = con.cursor() # ------------ smallint ------------- data = [ [32767, -32768] ] try_insert(con, cur, 'v_smallint', data) # ------------ int ------------- data = [ [2147483647, -2147483648] ] try_insert(con, cur, 'v_integer', data) # ------------ bigint ------------- data = [ [9223372036854775807, -9223372036854775808] ] try_insert(con, cur, 'v_bigint', data) # ------------ int128 ------------- # sqltype: 32752 INT128 Nullable scale: 0 subtype: 0 len: 16 # ValueError: Incorrect ARRAY field value. # !! WRONG!! >>> data = [ [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')] ] # Only INTEGERS must be specified as arguments: data = [ [170141183460469231731687303715884105727, -170141183460469231731687303715884105728] ] try_insert(con, cur, 'v_int128', data) # ------------ double ------------- data = [ [-2.2250738585072014e-308, 1.7976931348623158e+308] ] try_insert(con, cur, 'v_double', data) # ------------ decfloat ------------- # ValueError: Incorrect ARRAY field value. # data = [ [Decimal('-1.0E-6143'), Decimal('9.999999999999999999999999999999999E6144')] ] # data = [ [-1.0E-6143, 9.999999999999999999999999999999999E6144] ] data = [ [Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')] ] try_insert(con, cur, 'v_decfloat', data) backup = BytesIO() with act.connect_server() as srv: srv.database.local_backup(database=act.db.db_path, backup_stream=backup) backup.seek(0) srv.database.local_restore(backup_stream=backup, database=act.db.db_path, flags = SrvRestoreFlag.REPLACE) with act.db.connect() as con: cur = con.cursor() for fld_name in ('v_smallint','v_integer','v_bigint','v_int128','v_double', 'v_decfloat'): cur.execute(f'select {fld_name} from test_arr') for r in cur: # type(r): if any(r): print(f'Result after restore for column {fld_name}:') for p in r: print(p) act.expected_stdout = """ Trying to add array in v_smallint Data: [[32767, -32768]] 32767 -32768 Success. Trying to add array in v_integer Data: [[2147483647, -2147483648]] 2147483647 -2147483648 Success. Trying to add array in v_bigint Data: [[9223372036854775807, -9223372036854775808]] 9223372036854775807 -9223372036854775808 Success. Trying to add array in v_int128 Data: [[170141183460469231731687303715884105727, -170141183460469231731687303715884105728]] 170141183460469231731687303715884105727 -170141183460469231731687303715884105728 Success. Trying to add array in v_double Data: [[-2.2250738585072014e-308, 1.7976931348623157e+308]] -2.2250738585072014e-308 1.7976931348623157e+308 Success. Trying to add array in v_decfloat Data: [[Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')]] -9.999999999999999999999999999999999E+6144 9.999999999999999999999999999999999E+6144 Success. Result after restore for column v_smallint: [32767, -32768] Result after restore for column v_integer: [2147483647, -2147483648] Result after restore for column v_bigint: [9223372036854775807, -9223372036854775808] Result after restore for column v_int128: [Decimal('170141183460469231731687303715884105727'), Decimal('-170141183460469231731687303715884105728')] Result after restore for column v_double: [-2.2250738585072014e-308, 1.7976931348623157e+308] Result after restore for column v_decfloat: [Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')] """ act.stdout = capsys.readouterr().out assert act.clean_stdout == act.clean_expected_stdout