Files
cobol-java-v3/tests/cobol_testgen/test_to_sql_between_dbinput.py
T

189 lines
8.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""SELECT BETWEEN WHERE 约束的 DB 预置行生成测试(Phase 2)。
根因:KYU05DED 的 `WHERE :WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO`
在修复解析后成为 between 约束,但 build_db_input 不处理 between 类型,
TAX_FROM/TAX_TO 仍落入默认序号值 → 运行时 SELECT 查不到行 → SQLCODE<>0。
修复:build_db_input 对 between 约束,用记录中的 subject 值播种 lo/hi 列,
使运行时 `:hv BETWEEN TAX-FROM AND TAX-TO` 能命中。
"""
import sys, os
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")))
from cobol_testgen.to_sql import build_db_input
def _sql_meta_select_between():
return [{
"type": "exec_sql_select",
"table": "TAX-TABLE",
"select_list": "TAX-RATE, DEDUCTION",
"into_vars": ["DBV-TAX-RATE", "DBV-TAX-DEDUCTION"],
"where": ":WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO",
"where_constraints": [
{"type": "between", "neg": False, "op": "BETWEEN",
"subject": {"kind": "host_var", "name": "WRK-TAXABLE-INCOME"},
"lo": {"kind": "column", "name": "TAX-FROM"},
"hi": {"kind": "column", "name": "TAX-TO"}},
],
}]
def _declared_tax_table():
return {
"TAX-TABLE": [
{"name": "TAX_FROM", "db_type": "DECIMAL"},
{"name": "TAX_TO", "db_type": "DECIMAL"},
{"name": "TAX_RATE", "db_type": "DECIMAL"},
{"name": "DEDUCTION", "db_type": "DECIMAL"},
],
}
def test_select_between_hostvar_subject_seeds_lo_hi_from_record():
"""`:hv BETWEEN TAX-FROM AND TAX-TO`TAX_FROM/TAX_TO 播成记录中
WRK-TAXABLE-INCOME 的值,保证运行时 BETWEEN 命中。"""
records = [{"WRK-TAXABLE-INCOME": "000000000"}]
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], [], {},
_sql_meta_select_between(), _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert len(rows) == 1
assert int(rows[0]['TAX_FROM']) == 0
assert int(rows[0]['TAX_TO']) == 0
def test_select_between_hostvar_subject_nonzero():
"""subject 非零时,lo/hi 取记录值。"""
records = [{"WRK-TAXABLE-INCOME": "000102400"}]
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], [], {},
_sql_meta_select_between(), _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert len(rows) == 1
assert int(rows[0]['TAX_FROM']) == 102400
assert int(rows[0]['TAX_TO']) == 102400
def test_select_between_hostvar_subject_moved_from_input():
"""subject 主机变量经 MOVE 链到输入键时,优先用输入键值。"""
sql_meta = [{
"type": "exec_sql_select",
"table": "TAX-TABLE",
"select_list": "TAX-RATE, DEDUCTION",
"into_vars": ["DBV-TAX-RATE", "DBV-TAX-DEDUCTION"],
"where": ":WRK-TAXABLE-INCOME BETWEEN TAX-FROM AND TAX-TO",
"where_constraints": [
{"type": "between", "neg": False, "op": "BETWEEN",
"subject": {"kind": "host_var", "name": "WRK-TAXABLE-INCOME"},
"lo": {"kind": "column", "name": "TAX-FROM"},
"hi": {"kind": "column", "name": "TAX-TO"}},
],
}]
records = [{"R01GROSS-PAYMENT": "000102400",
"WRK-TAXABLE-INCOME": "000000000"}]
assignments = {
'WRK-TAXABLE-INCOME': [{'type': 'move', 'source_vars': ['R01GROSS-PAYMENT']}],
}
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], [], assignments,
sql_meta, _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert len(rows) == 1
assert int(rows[0]['TAX_FROM']) == 102400
def test_select_between_column_subject_seeds_subject_col():
"""`SALARY BETWEEN :LO AND :HI`subject 是列时,把该列播成 lo 值
(满足 lo <= col <= hi)。"""
sql_meta = [{
"type": "exec_sql_select",
"table": "EMP",
"select_list": "EMP_NAME",
"into_vars": ["DBV-EMPLOYEE-NAME"],
"where": "SALARY BETWEEN :LO AND :HI",
"where_constraints": [
{"type": "between", "neg": False, "op": "BETWEEN",
"subject": {"kind": "column", "name": "SALARY"},
"lo": {"kind": "host_var", "name": "LO"},
"hi": {"kind": "host_var", "name": "HI"}},
],
}]
declared = {
"EMP": [
{"name": "SALARY", "db_type": "DECIMAL"},
{"name": "EMP_NAME", "db_type": "CHAR", "size": 40},
],
}
records = [{"LO": "000005000", "HI": "000009000"}]
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], [], {},
sql_meta, declared, records=records)
rows = db_input.get('EMP', [])
assert len(rows) == 1
sal = int(rows[0]['SALARY'])
assert 5000 <= sal <= 9000
def test_select_between_sql_error_path_skips_row():
"""SQL 失败路径(SQLCODE<>0)仍不生成预置行。"""
records = [{"WRK-TAXABLE-INCOME": "000102400"}]
db_input = build_db_input(
[([('SQLCODE', '<>', '0', True)], {})], [], {},
_sql_meta_select_between(), _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert not rows
def _fdict_with_ws_constants():
"""KYU05DED 简化的字段定义:CNS-TAX-BASIC-DEDUCTION 常量 + MOVE/COMPUTE 链。"""
return [
{'name': 'R01GROSS-PAYMENT', 'pic_info': {'type': 'numeric', 'digits': 9, 'decimal': 0, 'length': 0, 'signed': False}, 'section': 'INPUT', 'value': None},
{'name': 'WRK-GROSS-PAYMENT', 'pic_info': {'type': 'numeric', 'digits': 9, 'decimal': 0, 'length': 0, 'signed': False}, 'section': 'WORKING-STORAGE', 'value': None},
{'name': 'WRK-TAXABLE-INCOME', 'pic_info': {'type': 'numeric', 'digits': 9, 'decimal': 0, 'length': 0, 'signed': False}, 'section': 'WORKING-STORAGE', 'value': None},
{'name': 'CNS-TAX-BASIC-DEDUCTION', 'pic_info': {'type': 'numeric', 'digits': 6, 'decimal': 0, 'length': 0, 'signed': False}, 'section': 'WORKING-STORAGE', 'value': '50000'},
]
def test_select_between_derives_runtime_value_from_input_key():
"""记录中 WRK-TAXABLE-INCOME 为合成值时,按运行时推导值播种带。
输入 gross=000100000 → 运行时 taxable = gross - 50000 = 50000
预置行 TAX_FROM/TAX_TO 应为 50000,而非记录的合成值。"""
assignments = {
'WRK-GROSS-PAYMENT': [{'type': 'move', 'source_vars': ['R01GROSS-PAYMENT']}],
'WRK-TAXABLE-INCOME': [
{'type': 'move_literal', 'literal': 'ZERO'},
{'type': 'compute', 'source_vars': ['WRK-GROSS-PAYMENT', 'CNS-TAX-BASIC-DEDUCTION'], 'op': '-'},
],
}
records = [{"R01GROSS-PAYMENT": "000100000",
"WRK-TAXABLE-INCOME": "000003701"}]
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], _fdict_with_ws_constants(), assignments,
_sql_meta_select_between(), _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert len(rows) == 1
assert int(rows[0]['TAX_FROM']) == 50000
assert int(rows[0]['TAX_TO']) == 50000
def test_select_between_derives_zero_for_low_gross():
"""gross < 基本控除(50000)时,运行时 taxable = 0 → 带为 [0,0]。"""
assignments = {
'WRK-GROSS-PAYMENT': [{'type': 'move', 'source_vars': ['R01GROSS-PAYMENT']}],
'WRK-TAXABLE-INCOME': [
{'type': 'move_literal', 'literal': 'ZERO'},
{'type': 'compute', 'source_vars': ['WRK-GROSS-PAYMENT', 'CNS-TAX-BASIC-DEDUCTION'], 'op': '-'},
],
}
records = [{"R01GROSS-PAYMENT": "000000501",
"WRK-TAXABLE-INCOME": "000003701"}]
db_input = build_db_input(
[([('SQLCODE', '=', '0', True)], {})], _fdict_with_ws_constants(), assignments,
_sql_meta_select_between(), _declared_tax_table(), records=records)
rows = db_input.get('TAX-TABLE', [])
assert len(rows) == 1
assert int(rows[0]['TAX_FROM']) == 0
assert int(rows[0]['TAX_TO']) == 0