"""BETWEEN WHERE 子句解析测试。 根因:KYU05DED 的 `WHERE :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO`: 1. `_split_on_AND` 把 BETWEEN 内部的 AND 当成分隔符切断,导致约束解析为空; 2. `_RE_BETWEEN` 要求首操作数为列名,不支持 `:主机变量 BETWEEN ...`。 修复后应能解析出 subject / lo / hi 三端(每端可为列名 / 主机变量 / 字面量)。 """ import sys, os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) from cobol_testgen.to_sql import _split_on_AND, sql_extract_constraints def test_split_on_and_preserves_between(): """BETWEEN 内部的 AND 不应被当作条件分隔符切断。""" parts = _split_on_AND(':WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO') assert parts == [':WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO'] def test_split_on_and_between_with_following_and(): """BETWEEN 后的其他 AND 条件仍应正确切分。""" parts = _split_on_AND( 'EMP-ID = :DBV-EMP-ID AND :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO AND STATUS = :S' ) assert parts == [ 'EMP-ID = :DBV-EMP-ID', ':WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO', 'STATUS = :S', ] def test_sql_extract_constraints_between_hostvar_subject(): """`:主机变量 BETWEEN 列1 AND 列2`:subject 为主机变量,lo/hi 为列名。""" cons = sql_extract_constraints( ':WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO', 'TAX_TABLE', {}, {}, {}) assert len(cons) == 1 c = cons[0] assert c['type'] == 'between' assert c['neg'] is False assert c['subject'] == {'kind': 'host_var', 'name': 'WRK-TAXABLE-INCOME'} assert c['lo'] == {'kind': 'column', 'name': 'TAX-FROM'} assert c['hi'] == {'kind': 'column', 'name': 'TAX-TO'} def test_sql_extract_constraints_between_column_subject(): """`列 BETWEEN :低 AND :高`:subject 为列名,lo/hi 为主机变量。""" cons = sql_extract_constraints( 'SALARY BETWEEN :LO AND :HI', 'EMP', {}, {}, {}) assert len(cons) == 1 c = cons[0] assert c['type'] == 'between' assert c['subject'] == {'kind': 'column', 'name': 'SALARY'} assert c['lo'] == {'kind': 'host_var', 'name': 'LO'} assert c['hi'] == {'kind': 'host_var', 'name': 'HI'} def test_sql_extract_constraints_between_compound(): """BETWEEN 与其他条件组合时,全部解析且顺序保持。""" cons = sql_extract_constraints( 'EMP-ID = :DBV-EMP-ID AND :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO', 'TAX_TABLE', {}, {}, {}) assert len(cons) == 2 assert cons[0]['type'] == 'host_var' assert cons[0]['host_var'] == 'DBV-EMP-ID' assert cons[1]['type'] == 'between' def test_sql_extract_constraints_not_between(): """NOT BETWEEN 正确解析 neg 标志。""" cons = sql_extract_constraints(':X NOT BETWEEN A AND B', 'T', {}, {}, {}) assert len(cons) == 1 assert cons[0]['type'] == 'between' assert cons[0]['neg'] is True assert cons[0]['subject'] == {'kind': 'host_var', 'name': 'X'} def test_sql_extract_constraints_between_three_part(): """三段式:BETWEEN 之后跟后续 AND 条件。""" cons = sql_extract_constraints( ':X BETWEEN A AND B AND :Y > 5', 'T', {}, {}, {}) assert len(cons) == 2 assert cons[0]['type'] == 'between' assert cons[0]['lo'] == {'kind': 'column', 'name': 'A'} assert cons[0]['hi'] == {'kind': 'column', 'name': 'B'} assert cons[1]['type'] == 'literal' assert cons[1]['op'] == '>'