mirror of
https://github.com/FirebirdSQL/firebird-qa.git
synced 2025-01-22 21:43:06 +01:00
191 lines
8.1 KiB
Python
191 lines
8.1 KiB
Python
#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): <class 'tuple'>
|
|
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 <class 'int'>
|
|
-32768 <class 'int'>
|
|
Success.
|
|
|
|
Trying to add array in v_integer
|
|
Data: [[2147483647, -2147483648]]
|
|
2147483647 <class 'int'>
|
|
-2147483648 <class 'int'>
|
|
Success.
|
|
|
|
Trying to add array in v_bigint
|
|
Data: [[9223372036854775807, -9223372036854775808]]
|
|
9223372036854775807 <class 'int'>
|
|
-9223372036854775808 <class 'int'>
|
|
Success.
|
|
|
|
Trying to add array in v_int128
|
|
Data: [[170141183460469231731687303715884105727, -170141183460469231731687303715884105728]]
|
|
170141183460469231731687303715884105727 <class 'decimal.Decimal'>
|
|
-170141183460469231731687303715884105728 <class 'decimal.Decimal'>
|
|
Success.
|
|
|
|
Trying to add array in v_double
|
|
Data: [[-2.2250738585072014e-308, 1.7976931348623157e+308]]
|
|
-2.2250738585072014e-308 <class 'float'>
|
|
1.7976931348623157e+308 <class 'float'>
|
|
Success.
|
|
|
|
Trying to add array in v_decfloat
|
|
Data: [[Decimal('-9.999999999999999999999999999999999E+6144'), Decimal('9.999999999999999999999999999999999E+6144')]]
|
|
-9.999999999999999999999999999999999E+6144 <class 'decimal.Decimal'>
|
|
9.999999999999999999999999999999999E+6144 <class 'decimal.Decimal'>
|
|
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
|