|
| 1 | +#coding:utf-8 |
| 2 | + |
| 3 | +""" |
| 4 | +ID: issue-8418 |
| 5 | +ISSUE: https://github.com/FirebirdSQL/firebird/issues/8418 |
| 6 | +TITLE: Character <S> must NOT occur in any value generated by UNLIST which gets this <S> as separator. |
| 7 | +DESCRIPTION: |
| 8 | + Test restores two databases (clones of employee) that contain blob field that must be passed as argument to UNLIST(). |
| 9 | + In both DB blobs were generated as random sequences of unicode characters from any avaliable ranges. |
| 10 | + None of values generated by UNLIST() must contain separator. |
| 11 | + But under some circumstatences this rule could be violated, see: |
| 12 | + https://github.com/FirebirdSQL/firebird/pull/8418#issuecomment-2781057324 |
| 13 | + https://github.com/FirebirdSQL/firebird/pull/8418#issuecomment-2789227832 |
| 14 | +NOTES: |
| 15 | + Confirmed bug on 6.0.0.742 (17-apr-2025): separator presented in some of generated values. |
| 16 | + Checked on 6.0.0.744 (19-apr-2025) - all fine. |
| 17 | +""" |
| 18 | + |
| 19 | +from pathlib import Path |
| 20 | +import zipfile |
| 21 | +import locale |
| 22 | +import pytest |
| 23 | +from firebird.qa import * |
| 24 | +from firebird.driver import connect |
| 25 | + |
| 26 | +db = db_factory(charset = 'utf8') |
| 27 | +act = python_act('db', substitutions=[('[ \t]+', ' ')]) |
| 28 | + |
| 29 | +tmp_fbk = temp_file('unlist_unexpected.tmp.fbk') |
| 30 | +tmp_fdb = temp_file('unlist_unexpected.tmp.fdb') |
| 31 | + |
| 32 | +@pytest.mark.version('>=6.0.0') |
| 33 | +def test_1(act: Action, tmp_fbk: Path, tmp_fdb: Path, capsys): |
| 34 | + |
| 35 | + test_map = {'unlist-unexpected-6_0_0_716-a5b25c1.fbk' : '0x227b', 'unlist-unexpected-6_0_0_717-fbb6b0c.fbk' : '0x2114'} |
| 36 | + expected_out = [] |
| 37 | + for i_fbk, i_chr in test_map.items(): |
| 38 | + |
| 39 | + # 716: select u.* from unlist((select blob_fld from t_longblob), unicode_char(0x227b) returning blob character set utf8) as u(x) where x containing unicode_char(0x227b) |
| 40 | + # 717: select u.x, octet_length(u.x), position(unicode_char(0x2114) in u.x), unicode_char(0x2114) from unlist((select blob_fld from t_longblob), unicode_char(0x2114) returning blob character set utf8) as u(x) where x containing unicode_char(0x2114) |
| 41 | + |
| 42 | + zipped_fbk_file = zipfile.Path(act.files_dir / 'unlist-unexpected.zip', at = i_fbk) |
| 43 | + tmp_fbk.write_bytes(zipped_fbk_file.read_bytes()) |
| 44 | + |
| 45 | + act.gbak(switches = ['-rep', str(tmp_fbk), str(tmp_fdb)], combine_output = True, io_enc = locale.getpreferredencoding()) |
| 46 | + assert '' == act.stdout |
| 47 | + act.reset() |
| 48 | + |
| 49 | + test_sql = f""" |
| 50 | + with |
| 51 | + d as ( |
| 52 | + select |
| 53 | + blob_fld |
| 54 | + ,unicode_char({i_chr}) as separator |
| 55 | + from t_longblob |
| 56 | + ) |
| 57 | + , e as ( |
| 58 | + select * from d, unlist(d.blob_fld, d.separator returning blob character set utf8) as u (unlist_token) |
| 59 | + ) |
| 60 | + select e.unlist_token, position(e.separator in e.unlist_token) as separator_pos |
| 61 | + from e |
| 62 | + where e.unlist_token containing e.separator |
| 63 | + ; |
| 64 | + """ |
| 65 | + |
| 66 | + with connect(str(tmp_fdb), user = act.db.user, password = act.db.password, charset = 'utf8') as con: |
| 67 | + print(i_fbk) |
| 68 | + expected_out.append(i_fbk) |
| 69 | + cur = con.cursor() |
| 70 | + cur.execute(test_sql) |
| 71 | + data = cur.fetchall() |
| 72 | + if data: |
| 73 | + print(f'### ERROR ### separator {i_chr} occurs at least in one record issued by UNLIST():') |
| 74 | + |
| 75 | + col = cur.description |
| 76 | + for r in data: |
| 77 | + for i in range(len(col)): |
| 78 | + print(' '.join((col[i][0], ':', str(r[i])))) |
| 79 | + |
| 80 | + |
| 81 | + act.expected_stdout = '\n'.join(expected_out) |
| 82 | + |
| 83 | + act.stdout = capsys.readouterr().out |
| 84 | + assert act.clean_stdout == act.clean_expected_stdout |
0 commit comments