The Computing Series

Where It Fails

FM8 — Schema/Contract Violation

Two expressions believed to be equivalent that are not.

This happens in three ways:

1. Incorrect mental application of equivalence laws.

# Developer believes these are equivalent
# Original: "process if admin OR (editor AND not read_only)"
def can_edit_original(is_admin: bool, is_editor: bool, is_read_only: bool) -> bool:
    return is_admin or (is_editor and not is_read_only)

# "Simplified" version: pulls out NOT incorrectly
def can_edit_wrong(is_admin: bool, is_editor: bool, is_read_only: bool) -> bool:
    # Developer thinks: factor out "not is_read_only" from the whole expression
    # This is NOT the same as the original
    return (is_admin or is_editor) and not is_read_only

# Test to reveal the difference
# Inputs: is_admin=False, is_editor=False, is_read_only=False
print(can_edit_original(False, False, False))   # False (not editor, not admin)
print(can_edit_wrong(False, False, False))       # False (same)

# Inputs: is_admin=True, is_editor=False, is_read_only=True
print(can_edit_original(True, False, True))     # True (admin overrides)
print(can_edit_wrong(True, False, True))         # True AND False = False (WRONG)

The second version is not equivalent to the first. An admin with is_read_only=True is incorrectly blocked. The “simplification” introduced a bug.

2. Equivalence that holds for most data but not all.

SQL query rewrites can fail when NULL values are involved. Classical boolean equivalence does not hold in three-valued SQL logic. The optimizer must account for NULL separately.

-- These are NOT equivalent in SQL due to NULL:
WHERE NOT (status = 'active' AND type = 'premium')
-- vs.
WHERE status != 'active' OR type != 'premium'

-- If status IS NULL:
-- First expression: NOT (NULL AND ...) = NOT NULL = NULL (unknown)
-- Second expression: NULL OR ... = NULL or the other side
-- They may evaluate differently for NULL inputs

3. Equivalence that depends on evaluation order (non-commutative systems).

In databases with row-level security, predicates can produce different results depending on which user context they are evaluated in. Two expressions equivalent in one security context may not be equivalent in another.


Read in the book →