약한 개체 타입 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.

"""약한 개체 타입 검증.

문서: 27.약한 개체 타입 (예시로 보기, 카드 C1·C3), 28.일반 개체 타입과 약한 개체 타입 비교
출처: Elmasri & Navathe, Fundamentals of Database Systems 3장의 DEPENDENT 예와 COMPANY 상태
주장:
  1. DEPENDENT 7명 가운데 이름 Alice가 두 명이다(Wong의 딸, Smith의 딸).
     Dependent_name만으로는 부양가족을 가려내지 못한다.
  2. 주인 직원(Essn)과 이름을 함께 대면 7명이 모두 가려진다. Dependent_name은 부분 키다.
  3. 생일(Bdate)은 이 7명에서 우연히 다 다르지만, 생일이 같은 부양가족이 들어오면 깨진다. 키가 아니다.
  4. 부양가족은 모두 실제로 있는 직원에 딸려 있다(전체 참여). 직원 8명 중 부양가족이 있는 직원은 3명(부분 참여).
"""

# COMPANY 상태의 DEPENDENT: (Essn, Dependent_name, Sex, Bdate, Relationship)
DEPENDENT = [("333445555", "Alice", "F", "1986-04-05", "Daughter"), ("333445555", "Theodore", "M", "1983-10-25", "Son"),
             ("333445555", "Joy", "F", "1958-05-03", "Spouse"), ("987654321", "Abner", "M", "1942-02-28", "Spouse"),
             ("123456789", "Michael", "M", "1988-01-04", "Son"), ("123456789", "Alice", "F", "1988-12-30", "Daughter"),
             ("123456789", "Elizabeth", "F", "1967-05-05", "Spouse")]
EMPLOYEE_SSN = ["123456789", "333445555", "999887777", "987654321", "666884444", "453453453", "987987987", "888665555"]
ESSN, NAME, SEX, BDATE, REL = range(5)


def unique(rows, cols):
    seen = [tuple(r[c] for c in cols) for r in rows]
    return len(set(seen)) == len(seen)


def main():
    assert len(DEPENDENT) == 7 and not unique(DEPENDENT, [NAME])
    alices = sorted(r[ESSN] for r in DEPENDENT if r[NAME] == "Alice")
    assert alices == ["123456789", "333445555"]
    print("[OK] Alice가 두 명(직원 333445555와 123456789의 딸) -> 이름만으로는 못 가린다")

    assert unique(DEPENDENT, [ESSN, NAME])
    # 같은 직원 안에서는 이름이 겹치지 않는다
    for ssn in set(r[ESSN] for r in DEPENDENT):
        assert unique([r for r in DEPENDENT if r[ESSN] == ssn], [NAME])
    print("[OK] (주인 직원, 이름)은 7명이 모두 다르다 -> Dependent_name은 부분 키")

    assert not unique(DEPENDENT, [SEX]) and not unique(DEPENDENT, [REL])
    assert unique(DEPENDENT, [BDATE])
    twin = DEPENDENT + [("987654321", "Bella", "F", "1986-04-05", "Daughter")]  # 생일이 같은 부양가족(보충)
    assert not unique(twin, [BDATE]) and unique(twin, [ESSN, NAME])
    print("[OK] 생일은 우연히 다 다를 뿐이다: 같은 생일을 넣으면 겹치고, (주인, 이름)은 그대로 안 겹친다")

    assert all(r[ESSN] in EMPLOYEE_SSN for r in DEPENDENT)
    owners = sorted(set(r[ESSN] for r in DEPENDENT))
    assert len(owners) == 3 and len(EMPLOYEE_SSN) == 8
    print("[OK] 부양가족 7명 모두 주인 직원이 있다. 직원 8명 중 3명만 부양가족이 있다")

    print("ALL CHECKS PASSED")


if __name__ == "__main__":
    main()