exec-ddl
CREATE TABLE ab (
  a INT PRIMARY KEY,
  b INT,
  INDEX (b)
)
----

exec-ddl
CREATE TABLE uv (
  u INT PRIMARY KEY,
  v INT,
  INDEX (v)
)
----

exec-ddl
CREATE TABLE xy (
  x INT PRIMARY KEY,
  y INT,
  INDEX (y)
)
----

# This test ensures that a memo cycle does not cause a stack overflow. Instead,
# the cycle is detected and the optimizer throws an internal error. The cycle is
# created by the test-only exploration rule MemoCycleTestRelRule.
expropt disable=MemoCycleTestRelRuleFilter skip-race
(MemoCycleTestRel
    (Scan [ (Table "ab") (Cols "a,b") ])
    [ (Eq (Var "b") (Const 1 "int")) ]
)
----
error: memo group optimization passes surpassed limit of 100000; there may be a cycle in the memo
details:
memo (not optimized, ~3KB, required=[], cycle=[G1->G1])
 ├── G1: (memo-cycle-test-rel G2 G3) (memo-cycle-test-rel G1 G3)
 ├── G2: (scan ab,cols=(1,2)) (scan ab@ab_b_idx,cols=(1,2))
 │    └── []
 │         ├── best: (scan ab,cols=(1,2))
 │         └── cost: 1068.42
 ├── G3: (filters G4)
 ├── G4: (eq G5 G6)
 ├── G5: (variable b)
 └── G6: (const 1)

expropt disable=MemoCycleTestRelRuleFilter skip-race
(LeftJoin
    (Scan [ (Table "ab") (Cols "a,b") ])
    (LeftJoin
        (MemoCycleTestRel
            (Scan [ (Table "uv") (Cols "u,v") ])
            [ (Eq (Var "v") (Const 1 "int")) ]
        )
        (Scan [ (Table "xy") (Cols "x,y") ])
        [ ]
        [ ]
    )
    [ ]
    [ ]
)
----
error: memo group optimization passes surpassed limit of 100000; there may be a cycle in the memo
details:
memo (not optimized, ~17KB, required=[], cycle=[G1->G3->G5->G5])
 ├── G1: (left-join G2 G3 G4)
 ├── G2: (scan ab,cols=()) (scan ab@ab_b_idx,cols=())
 │    └── []
 │         ├── best: (scan ab,cols=())
 │         └── cost: 1048.22
 ├── G3: (left-join G5 G6 G4)
 ├── G4: (filters)
 ├── G5: (memo-cycle-test-rel G7 G8) (memo-cycle-test-rel G5 G8)
 ├── G6: (scan xy,cols=())
 ├── G7: (scan uv,cols=(5,6)) (scan uv@uv_v_idx,cols=(5,6))
 │    └── []
 │         ├── best: (scan uv,cols=(5,6))
 │         └── cost: 1068.42
 ├── G8: (filters G9)
 ├── G9: (eq G10 G11)
 ├── G10: (variable v)
 └── G11: (const 1)

# Ensure that a cycle through a filter can be detected.
expropt disable=MemoCycleTestRelRule skip-race
(MemoCycleTestRel
    (Scan [ (Table "uv") (Cols "u,v") ])
    [ (Eq (Var "v") (Const 1 "int")) ]
)
----
error: memo group optimization passes surpassed limit of 100000; there may be a cycle in the memo
details:
memo (not optimized, ~6KB, required=[], cycle=[G1->G4->G6->G9->G10->G12->G13->G1])
 ├── G1: (memo-cycle-test-rel G2 G3) (select G2 G4)
 ├── G2: (scan uv,cols=(1,2)) (scan uv@uv_v_idx,cols=(1,2))
 │    ├── [limit hint: 1000.00]
 │    │    ├── best: (scan uv,cols=(1,2))
 │    │    └── cost: 1058.02
 │    └── []
 │         ├── best: (scan uv,cols=(1,2))
 │         └── cost: 1068.42
 ├── G3: (filters G5)
 ├── G4: (filters G6)
 ├── G5: (eq G7 G8)
 ├── G6: (coalesce G9)
 ├── G7: (variable v)
 ├── G8: (const 1)
 ├── G9: (scalar-list G10 G11)
 ├── G10: (subquery G12 &{<nil>  0 false unknown})
 ├── G11: (false)
 ├── G12: (project G13 G14)
 ├── G13: (limit G1 G8)
 ├── G14: (projections G15)
 └── G15: (true)
