# LogicTest: 5node-dist-opt

statement ok
CREATE TABLE abc (a INT, b INT, c INT, PRIMARY KEY (a, c))

statement ok
CREATE TABLE def (d INT, e INT, f INT, PRIMARY KEY (f, e))

# Set up the statistics as if the first table is much smaller than the second.
# This will make lookup join into the second table be the best plan.
statement ok
ALTER TABLE abc INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE def INJECT STATISTICS '[
  {
    "columns": ["f"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM abc JOIN def ON f = b
----
tree         field  description  columns             ordering
lookup-join  ·      ·            (a, b, c, d, e, f)  ·
 │           table  def@primary  ·                   ·
 │           type   inner        ·                   ·
 └── scan    ·      ·            (a, b, c)           ·
·            table  abc@primary  ·                   ·
·            spans  ALL          ·                   ·

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM abc JOIN def ON f = b WHERE a > 1 AND e > 1
----
tree         field  description  columns             ordering
lookup-join  ·      ·            (a, b, c, d, e, f)  ·
 │           table  def@primary  ·                   ·
 │           type   inner        ·                   ·
 │           pred   @5 > 1       ·                   ·
 └── scan    ·      ·            (a, b, c)           ·
·            table  abc@primary  ·                   ·
·            spans  /2-          ·                   ·

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM abc JOIN def ON f = a WHERE f > 1
----
tree         field  description  columns             ordering
lookup-join  ·      ·            (a, b, c, d, e, f)  ·
 │           table  def@primary  ·                   ·
 │           type   inner        ·                   ·
 │           pred   @6 > 1       ·                   ·
 └── scan    ·      ·            (a, b, c)           ·
·            table  abc@primary  ·                   ·
·            spans  /2-          ·                   ·

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM abc JOIN def ON f = b WHERE a >= e
----
tree         field  description  columns             ordering
lookup-join  ·      ·            (a, b, c, d, e, f)  ·
 │           table  def@primary  ·                   ·
 │           type   inner        ·                   ·
 │           pred   @1 >= @5     ·                   ·
 └── scan    ·      ·            (a, b, c)           ·
·            table  abc@primary  ·                   ·
·            spans  ALL          ·                   ·

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM abc JOIN def ON f = b AND a >= e
----
tree         field  description  columns             ordering
lookup-join  ·      ·            (a, b, c, d, e, f)  ·
 │           table  def@primary  ·                   ·
 │           type   inner        ·                   ·
 │           pred   @1 >= @5     ·                   ·
 └── scan    ·      ·            (a, b, c)           ·
·            table  abc@primary  ·                   ·
·            spans  ALL          ·                   ·

# Verify a distsql plan.
statement ok
CREATE TABLE data (a INT, b INT, c INT, d INT, PRIMARY KEY (a, b, c, d))

# Prevent the merge queue from immediately discarding our splits.
statement ok
SET CLUSTER SETTING kv.range_merge.queue_enabled = false;

# Split into ten parts.
statement ok
ALTER TABLE data SPLIT AT SELECT i FROM generate_series(1, 9) AS g(i)

# Relocate the ten parts to the five nodes.
statement ok
ALTER TABLE data EXPERIMENTAL_RELOCATE
  SELECT ARRAY[i%5+1], i FROM generate_series(0, 9) AS g(i)

# Verify data placement.
query TTTI colnames
SELECT start_key, end_key, replicas, lease_holder from [SHOW EXPERIMENTAL_RANGES FROM TABLE data]
----
start_key  end_key  replicas  lease_holder
NULL       /1       {1}       1
/1         /2       {2}       2
/2         /3       {3}       3
/3         /4       {4}       4
/4         /5       {5}       5
/5         /6       {1}       1
/6         /7       {2}       2
/7         /8       {3}       3
/8         /9       {4}       4
/9         NULL     {5}       5

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM (SELECT * FROM data WHERE c = 1) AS l NATURAL JOIN data AS r
----
render            ·         ·             (a, b, c, d)              ·
 │                render 0  a             ·                         ·
 │                render 1  b             ·                         ·
 │                render 2  c             ·                         ·
 │                render 3  d             ·                         ·
 └── lookup-join  ·         ·             (a, b, c, d, a, b, c, d)  ·
      │           table     data@primary  ·                         ·
      │           type      inner         ·                         ·
      └── scan    ·         ·             (a, b, c, d)              ·
·                 table     data@primary  ·                         ·
·                 spans     ALL           ·                         ·
·                 filter    c = 1         ·                         ·

query T
SELECT url FROM [EXPLAIN (DISTSQL) SELECT * FROM (SELECT * FROM data WHERE c = 1) AS l NATURAL JOIN data AS r]
----
https://cockroachdb.github.io/distsqlplan/decode.html#eJzElEFr2zAUx-_7FOKdZWxJTpoKBj4NMkY6ut6GD1r06LylkpFk2Cj57sPxoE5IZEFMerSsP_8fvyfeKxircaNe0IP8DgwocKAggEIJFBZQU2id3aL31vVXhsBa_wFZUGhM24X-uKawtQ5BvkJowg5BwpP6scNHVBpdXgAFjUE1u0NN65oX5f5WWgUFFL61ynhJspwRZTRhxIaf6IDCp2YX0ElSCfKRMCnlevO0gnpPwXbhrdkH9Ywg2Z6m0322jfkPt4jCfbH2d9eSX7YxxBpJKkYrTitBq17QQxeOjy7B8Ytwb0ydsU6jQ30EVO_P4G9sZtucFSc3z3eLo26WPjaWMracZTmfcXATfKPBLW8_OJ4ujyfJ41kuZpQ3wTeSd3d7eSJdnkiSJ7K8nFHeBN9I3ur28sp0eWWSvDLLFzPKm-Abybt_3317Bu4RfWuNx6RtWvT7GPUzDsvb285t8auz20PN8PlwyB0ONPow_GXDx9oMv3rAcZhFw_wozE7DPN48US2i6TIeLq_hXkTDy3jz8prmu2h4FW9eXdN8H59VMfFM4o_stLvef_gXAAD__0eIKhg=

statement ok
CREATE TABLE books (title STRING, edition INT, shelf INT, PRIMARY KEY (title, edition))

statement ok
CREATE TABLE books2 (title STRING, edition INT, shelf INT, PRIMARY KEY (title, edition))

statement ok
ALTER TABLE books INJECT STATISTICS '[
  {
    "columns": ["title"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE books2 INJECT STATISTICS '[
  {
    "columns": ["title"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 1000
  }
]'

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT DISTINCT b1.title FROM books as b1 JOIN books2 as b2 ON b1.title = b2.title WHERE b1.shelf <> b2.shelf
----
tree                   field        description     columns                       ordering
distinct               ·            ·               (title)                       weak-key(title); +title
 │                     distinct on  title           ·                             ·
 │                     order key    title           ·                             ·
 └── render            ·            ·               (title)                       +title
      │                render 0     title           ·                             ·
      └── lookup-join  ·            ·               (title, shelf, title, shelf)  +title
           │           table        books2@primary  ·                             ·
           │           type         inner           ·                             ·
           │           pred         @2 != @4        ·                             ·
           └── scan    ·            ·               (title, shelf)                +title
·                      table        books@primary   ·                             ·
·                      spans        ALL             ·                             ·

statement ok
CREATE TABLE authors (name STRING, book STRING)

statement ok
ALTER TABLE authors INJECT STATISTICS '[
  {
    "columns": ["name"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT DISTINCT authors.name FROM books AS b1, books2 AS b2, authors WHERE b1.title = b2.title AND authors.book = b1.title AND b1.shelf <> b2.shelf
----
tree                        field        description       columns                                   ordering
distinct                    ·            ·                 (name)                                    weak-key(name)
 │                          distinct on  name              ·                                         ·
 └── render                 ·            ·                 (name)                                    ·
      │                     render 0     name              ·                                         ·
      └── hash-join         ·            ·                 (title, shelf, title, shelf, name, book)  ·
           │                type         inner             ·                                         ·
           │                equality     (title) = (book)  ·                                         ·
           ├── lookup-join  ·            ·                 (title, shelf, title, shelf)              ·
           │    │           table        books2@primary    ·                                         ·
           │    │           type         inner             ·                                         ·
           │    │           pred         @2 != @4          ·                                         ·
           │    └── scan    ·            ·                 (title, shelf)                            ·
           │                table        books@primary     ·                                         ·
           │                spans        ALL               ·                                         ·
           └── scan         ·            ·                 (name, book)                              ·
·                           table        authors@primary   ·                                         ·
·                           spans        ALL               ·                                         ·

# Verify data placement.
query TTTI colnames
SELECT start_key, end_key, replicas, lease_holder from [SHOW EXPERIMENTAL_RANGES FROM TABLE books]
----
start_key  end_key  replicas  lease_holder
NULL       NULL     {5}       5

# TODO(radu): this doesn't seem to be a lookup join, but it should be.

query T
SELECT url FROM [EXPLAIN (DISTSQL) SELECT DISTINCT authors.name FROM books AS b1, books2 AS b2, authors WHERE b1.title = b2.title AND authors.book = b1.title AND b1.shelf <> b2.shelf]
----
https://cockroachdb.github.io/distsqlplan/decode.html#eJyck89q3DAQh-99CndOCSjYku0cDAEdemhK2ZS0t7IHxZruqnE0RpKhJey7F9mlWZu10s1Rf76Zb362nsGSxo16Qg_Nd-DAoIYtg95Ri96Ti9vTpVv9C5qCgbH9EOL2lkFLDqF5hmBCh9DAhq6oz2tgoDEo043XDgxoCC-QD2qH0Fwf2FFhni78TT10eI9Ko8uLWXnonXlS7rd8IHr0wOBrr6xvsitgcDeEJpOcyRLWLPg5Fp_I2L8SPCEhgMFnosehz36SsRnZaBF9NpkU2fubTNbHdoLJksl61VG8NSlxWlINYR-_7OmsxKpHuerx0n6w5DQ61Mt_4PUrJ4b5qPw-ho4uL-ezdPgjXEh-eePMbh8upLj8N8N6kNU5QX4wPhjbhryad5Z8tX49q__KW7lH35P1-F-PpYjpoN7hlLanwbX4xVE7tpmWdyM3bmj0YTq9nha3djqKgscwT8IiDYskXM1gvoTLM2CxhKskXKe16yRcLODt4d2fAAAA__8CwK1z

query TTTTT colnames
EXPLAIN (VERBOSE) SELECT a.name FROM authors AS a JOIN books2 AS b2 ON a.book = b2.title ORDER BY a.name
----
tree                 field     description      columns              ordering
render               ·         ·                (name)               +name
 │                   render 0  name             ·                    ·
 └── lookup-join     ·         ·                (name, book, title)  +name
      │              table     books2@primary   ·                    ·
      │              type      inner            ·                    ·
      └── sort       ·         ·                (name, book)         +name
           │         order     +name            ·                    ·
           └── scan  ·         ·                (name, book)         ·
·                    table     authors@primary  ·                    ·
·                    spans     ALL              ·                    ·

# Cross joins should not be planned as lookup joins.
query TTTTT colnames
EXPLAIN (VERBOSE) SELECT * FROM books CROSS JOIN books2
----
tree            field     description     columns                                         ordering
render          ·         ·               (title, edition, shelf, title, edition, shelf)  ·
 │              render 0  title           ·                                               ·
 │              render 1  edition         ·                                               ·
 │              render 2  shelf           ·                                               ·
 │              render 3  title           ·                                               ·
 │              render 4  edition         ·                                               ·
 │              render 5  shelf           ·                                               ·
 └── hash-join  ·         ·               (title, edition, shelf, title, edition, shelf)  ·
      │         type      cross           ·                                               ·
      ├── scan  ·         ·               (title, edition, shelf)                         ·
      │         table     books2@primary  ·                                               ·
      │         spans     ALL             ·                                               ·
      └── scan  ·         ·               (title, edition, shelf)                         ·
·               table     books@primary   ·                                               ·
·               spans     ALL             ·                                               ·


query T
SELECT url FROM [EXPLAIN (DISTSQL) SELECT * FROM authors INNER JOIN books2 ON books2.edition = 1 WHERE books2.title = authors.book]
----
https://cockroachdb.github.io/distsqlplan/decode.html#eJyUkVFLwzAQx9_9FOGeb6zpNpCAkNeJdDL3Jn3I2mPWbbmQpKCMfndpI7iJq_p4_7vf5UfuBJZrKsyRAqhnkICwgBLBea4oBPZ9nIaW9RuoDKGxro19XCJU7AnUCWITDwQKCp6wm-aAUFM0zWEY6xC4jV9QiGZHoGYdni2W44s3ZnugNZma_DS7WA_ON0fj37Vp40vvi_DkjA1KTABh1UYltESdwzUP-R-Pe27sp4b8WWPLvA_9Dzww71snXrmxgq0Sug9XhdBzcSekUmpZbG4vFFHPUM9RL6665heuvxxjTcGxDfSna2RdiUD1jtLBA7e-okfP1fBMKlcDNwQ1hZi6s1QsbWr1guewHIXzcTgfhbNvcNndfAQAAP__24voVg==

####################################
#  LOOKUP JOIN ON SECONDARY INDEX  #
####################################

statement ok
CREATE TABLE small (a INT PRIMARY KEY, b INT, c INT, d INT)

statement ok
CREATE TABLE large (a INT, b INT, c INT, d INT, PRIMARY KEY (a, b), INDEX bc (b) STORING (c))

statement ok
ALTER TABLE small SPLIT AT SELECT i FROM generate_series(1, 9) AS g(i)

statement ok
ALTER TABLE small EXPERIMENTAL_RELOCATE
  SELECT ARRAY[i%5+1], i FROM generate_series(0, 9) AS g(i)

statement ok
INSERT INTO small SELECT x, 2*x, 3*x, 4*x FROM
  generate_series(1, 10) AS a(x)

statement ok
ALTER TABLE small INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 100,
    "distinct_count": 100
  }
]'

statement ok
ALTER TABLE large INJECT STATISTICS '[
  {
    "columns": ["a"],
    "created_at": "2018-01-01 1:00:00.00000+00:00",
    "row_count": 10000,
    "distinct_count": 10000
  }
]'

# Lookup join on covering secondary index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.a, large.c FROM small JOIN large ON small.a = large.b
----
render            ·         ·              (a, c)     ·
 │                render 0  a              ·          ·
 │                render 1  c              ·          ·
 └── lookup-join  ·         ·              (a, b, c)  ·
      │           table     large@bc       ·          ·
      │           type      inner          ·          ·
      └── scan    ·         ·              (a)        ·
·                 table     small@primary  ·          ·
·                 spans     ALL            ·          ·

# Lookup join on non-covering secondary index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.a, large.d FROM small JOIN large ON small.a = large.b
----
render                 ·         ·              (a, d)        ·
 │                     render 0  a              ·             ·
 │                     render 1  d              ·             ·
 └── lookup-join       ·         ·              (a, a, b, d)  ·
      │                table     large@primary  ·             ·
      │                type      inner          ·             ·
      └── lookup-join  ·         ·              (a, a, b)     ·
           │           table     large@bc       ·             ·
           │           type      inner          ·             ·
           └── scan    ·         ·              (a)           ·
·                      table     small@primary  ·             ·
·                      spans     ALL            ·             ·

############################
#  LEFT OUTER LOOKUP JOIN  #
############################

# Left join against primary index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.b, large.a FROM small LEFT JOIN large ON small.b = large.a
----
lookup-join  ·      ·              (b, a)  ·
 │           table  large@primary  ·       ·
 │           type   left outer     ·       ·
 └── scan    ·      ·              (b)     ·
·            table  small@primary  ·       ·
·            spans  ALL            ·       ·

# Left join should preserve input order.
query TTTTT
EXPLAIN (VERBOSE) SELECT t1.a, t2.b FROM small t1 LEFT JOIN large t2 ON t1.a = t2.a AND t2.b % 6 = 0 ORDER BY t1.a
----
render            ·         ·              (a, b)     +a
 │                render 0  a              ·          ·
 │                render 1  b              ·          ·
 └── lookup-join  ·         ·              (a, a, b)  +a
      │           table     large@primary  ·          ·
      │           type      left outer     ·          ·
      │           pred      (@3 % 6) = 0   ·          ·
      └── scan    ·         ·              (a)        +a
·                 table     small@primary  ·          ·
·                 spans     ALL            ·          ·

query T
SELECT url FROM [EXPLAIN (DISTSQL) SELECT t1.a, t2.b FROM small t1 LEFT JOIN large t2 ON t1.a = t2.a AND t2.b % 6 = 0 ORDER BY t1.a]
----
https://cockroachdb.github.io/distsqlplan/decode.html#eJzMlcGK2zwUhff_U4gLP7RUxpbtZDKCgjdTyDDYJXVXxQs1vqRuHctIMnQY8u4l9tDYQyMLvMkuknI4535HWC_QyBJTcUQN_BswoBAChQgoxEBhBQWFVsk9ai3V-S-DYFv-Bh5QqJq2M-ftgsJeKgT-AqYyNQKHXHyvcYeiROUHQKFEI6q6t2lVdRTqOdFHUddA4UsrGs2J5zMimpIwIs0PVEAh6wwnCYPiREF25mKmjTggcHai7oEeZdW85llN8-TPLXLy9PApJ9nX_GFHHrNtCvRvzlqoAwKFJyl_dS35KauGyKZPRiFLybskIv-TNed8m-ab9-QjCV5_X2agSXR1jPDqGJf0UpWosJwGT9gHKE7_mDWVnmx9NuV-zT6a2DP3WplTrT7z_HBRsTORRsWub7nY0J1s6EY29PxoEdmZSCOyd7dMNnInG7mRjTw_XkR2JtKI7OaWycbuZGM3srHnrxaRnYk0Int_y2RnXqsd6lY2Gp2-4MH5DcDygMOboWWn9vhZyX1vMyyzXtdvlKjNcMqGxbYZjs4Bx2JmFYcTMXsrDu3OM9aRVR3bxfGS3CureG13Xi9xvrOKN3bnzRLne3tXwcw1sV-yt97F6b8_AQAA___pW1AI

# Left join against covering secondary index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.c, large.c FROM small LEFT JOIN large ON small.c = large.b
----
render            ·         ·              (c, c)     ·
 │                render 0  c              ·          ·
 │                render 1  c              ·          ·
 └── lookup-join  ·         ·              (c, b, c)  ·
      │           table     large@bc       ·          ·
      │           type      left outer     ·          ·
      └── scan    ·         ·              (c)        ·
·                 table     small@primary  ·          ·
·                 spans     ALL            ·          ·

# Left join against non-covering secondary index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.c, large.d FROM small LEFT JOIN large ON small.c = large.b
----
render                 ·         ·              (c, d)        ·
 │                     render 0  c              ·             ·
 │                     render 1  d              ·             ·
 └── lookup-join       ·         ·              (c, a, b, d)  ·
      │                table     large@primary  ·             ·
      │                type      left outer     ·             ·
      └── lookup-join  ·         ·              (c, a, b)     ·
           │           table     large@bc       ·             ·
           │           type      left outer     ·             ·
           └── scan    ·         ·              (c)           ·
·                      table     small@primary  ·             ·
·                      spans     ALL            ·             ·

# Left join with ON filter on covering index
query TTTTT
EXPLAIN (VERBOSE) SELECT small.c, large.c FROM small LEFT JOIN large ON small.c = large.b AND large.c < 20
----
render            ·         ·              (c, c)     ·
 │                render 0  c              ·          ·
 │                render 1  c              ·          ·
 └── lookup-join  ·         ·              (c, b, c)  ·
      │           table     large@bc       ·          ·
      │           type      left outer     ·          ·
      │           pred      @3 < 20        ·          ·
      └── scan    ·         ·              (c)        ·
·                 table     small@primary  ·          ·
·                 spans     ALL            ·          ·

# Left join with ON filter on non-covering index
# TODO(radu): this doesn't use lookup join yet, the current rules don't cover
# left join with ON condition on columns that are not covered by the index.
query TTTTT
EXPLAIN (VERBOSE) SELECT small.c, large.d FROM small LEFT JOIN large ON small.c = large.b AND large.d < 30
----
render          ·         ·              (c, d)     ·
 │              render 0  c              ·          ·
 │              render 1  d              ·          ·
 └── hash-join  ·         ·              (b, d, c)  ·
      │         type      right outer    ·          ·
      │         equality  (b) = (c)      ·          ·
      ├── scan  ·         ·              (b, d)     ·
      │         table     large@primary  ·          ·
      │         spans     ALL            ·          ·
      │         filter    d < 30         ·          ·
      └── scan  ·         ·              (c)        ·
·               table     small@primary  ·          ·
·               spans     ALL            ·          ·

###########################################################
#  LOOKUP JOINS ON IMPLICIT INDEX KEY COLUMNS             #
#  https://github.com/cockroachdb/cockroach/issues/31777  #
###########################################################
statement ok
CREATE TABLE t (a INT, b INT, c INT, d INT, e INT)

statement ok
CREATE TABLE u (a INT, b INT, c INT, d INT, e INT, PRIMARY KEY (a DESC, b, c))

# Test index with all primary key columns implicit.
statement ok
CREATE INDEX idx ON u (d)

query TTTTT
EXPLAIN (VERBOSE) SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a WHERE t.e = 5
----
render            ·         ·          (a)              ·
 │                render 0  a          ·                ·
 └── lookup-join  ·         ·          (a, d, e, a, d)  ·
      │           table     u@idx      ·                ·
      │           type      inner      ·                ·
      └── scan    ·         ·          (a, d, e)        ·
·                 table     t@primary  ·                ·
·                 spans     ALL        ·                ·
·                 filter    e = 5      ·                ·

# Test unique version of same index. (Lookup join should not use column a.)
statement ok
DROP INDEX u@idx

statement ok
CREATE UNIQUE INDEX idx ON u (d)

query TTTTT
EXPLAIN (VERBOSE) SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a WHERE t.e = 5
----
render            ·         ·          (a)              ·
 │                render 0  a          ·                ·
 └── lookup-join  ·         ·          (a, d, e, a, d)  ·
      │           table     u@idx      ·                ·
      │           type      inner      ·                ·
      │           pred      @1 = @4    ·                ·
      └── scan    ·         ·          (a, d, e)        ·
·                 table     t@primary  ·                ·
·                 spans     ALL        ·                ·
·                 filter    e = 5      ·                ·

# Test index with first primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx CASCADE

statement ok
CREATE INDEX idx ON u (d, a)

query TTTTT
EXPLAIN (VERBOSE) SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.b = u.b WHERE t.e = 5
----
render            ·         ·          (a)                    ·
 │                render 0  a          ·                      ·
 └── lookup-join  ·         ·          (a, b, d, e, a, b, d)  ·
      │           table     u@idx      ·                      ·
      │           type      inner      ·                      ·
      └── scan    ·         ·          (a, b, d, e)           ·
·                 table     t@primary  ·                      ·
·                 spans     ALL        ·                      ·
·                 filter    e = 5      ·                      ·

# Test index with middle primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx

statement ok
CREATE INDEX idx ON u (d, b)

query TTTTT
EXPLAIN (VERBOSE) SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.b = u.b WHERE t.e = 5
----
render            ·         ·          (a)                    ·
 │                render 0  a          ·                      ·
 └── lookup-join  ·         ·          (a, b, d, e, a, b, d)  ·
      │           table     u@idx      ·                      ·
      │           type      inner      ·                      ·
      └── scan    ·         ·          (a, b, d, e)           ·
·                 table     t@primary  ·                      ·
·                 spans     ALL        ·                      ·
·                 filter    e = 5      ·                      ·

# Test index with last primary key column explicit and the rest implicit.
statement ok
DROP INDEX u@idx

statement ok
CREATE INDEX idx ON u (d, c)

query TTTTT
EXPLAIN (VERBOSE) SELECT u.a FROM t JOIN u ON t.d = u.d AND t.a = u.a AND t.d = u.d WHERE t.e = 5
----
render            ·         ·          (a)              ·
 │                render 0  a          ·                ·
 └── lookup-join  ·         ·          (a, d, e, a, d)  ·
      │           table     u@idx      ·                ·
      │           type      inner      ·                ·
      │           pred      @1 = @4    ·                ·
      └── scan    ·         ·          (a, d, e)        ·
·                 table     t@primary  ·                ·
·                 spans     ALL        ·                ·
·                 filter    e = 5      ·                ·

query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM def JOIN abc ON a=f ORDER BY a
----
render            ·         ·            (d, e, f, a, b, c)  ·
 │                render 0  d            ·                   ·
 │                render 1  e            ·                   ·
 │                render 2  f            ·                   ·
 │                render 3  a            ·                   ·
 │                render 4  b            ·                   ·
 │                render 5  c            ·                   ·
 └── lookup-join  ·         ·            (a, b, c, d, e, f)  +a
      │           table     def@primary  ·                   ·
      │           type      inner        ·                   ·
      └── scan    ·         ·            (a, b, c)           +a
·                 table     abc@primary  ·                   ·
·                 spans     ALL          ·                   ·

# Test that we don't get a lookup join if we force a merge join.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM def INNER MERGE JOIN abc ON a=f ORDER BY a
----
merge-join  ·               ·            (d, e, f, a, b, c)  +f
 │          type            inner        ·                   ·
 │          equality        (f) = (a)    ·                   ·
 │          mergeJoinOrder  +"(f=a)"     ·                   ·
 ├── scan   ·               ·            (d, e, f)           +f
 │          table           def@primary  ·                   ·
 │          spans           ALL          ·                   ·
 └── scan   ·               ·            (a, b, c)           +a
·           table           abc@primary  ·                   ·
·           spans           ALL          ·                   ·

# Test that we don't get a lookup join if we force a hash join.
query TTTTT
EXPLAIN (VERBOSE) SELECT * FROM def INNER HASH JOIN abc ON a=f ORDER BY a
----
sort            ·         ·            (d, e, f, a, b, c)  +f
 │              order     +f           ·                   ·
 └── hash-join  ·         ·            (d, e, f, a, b, c)  ·
      │         type      inner        ·                   ·
      │         equality  (f) = (a)    ·                   ·
      ├── scan  ·         ·            (d, e, f)           ·
      │         table     def@primary  ·                   ·
      │         spans     ALL          ·                   ·
      └── scan  ·         ·            (a, b, c)           ·
·               table     abc@primary  ·                   ·
·               spans     ALL          ·                   ·
