exec-ddl
CREATE TABLE a (k INT PRIMARY KEY, i INT, j INT, INDEX j(j))
----

exec-ddl
CREATE TABLE b (k INT PRIMARY KEY, i INT, j INT NOT NULL, INDEX j(j))
----

opt
SELECT * FROM a ORDER BY i LIMIT 10
----
top-k
 ├── columns: k:1!null i:2 j:3
 ├── internal-ordering: +2
 ├── k: 10
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10]
 ├── cost: 1175.36856
 ├── key: (1)
 ├── fd: (1)-->(2,3)
 ├── ordering: +2
 └── scan a
      ├── columns: k:1!null i:2 j:3
      ├── stats: [rows=1000]
      ├── cost: 1088.62
      ├── key: (1)
      └── fd: (1)-->(2,3)

# TopK has a lower cost than using a min aggregate.
opt
SELECT min(j+1) FROM a
----
scalar-group-by
 ├── columns: min:7
 ├── cardinality: [1 - 1]
 ├── immutable
 ├── stats: [rows=1]
 ├── cost: 1081.76333
 ├── key: ()
 ├── fd: ()-->(7)
 ├── top-k
 │    ├── columns: column6:6
 │    ├── internal-ordering: +6
 │    ├── k: 1
 │    ├── cardinality: [0 - 1]
 │    ├── immutable
 │    ├── stats: [rows=1]
 │    ├── cost: 1081.72333
 │    ├── key: ()
 │    ├── fd: ()-->(6)
 │    └── project
 │         ├── columns: column6:6
 │         ├── immutable
 │         ├── stats: [rows=333.3333]
 │         ├── cost: 1075.03667
 │         ├── select
 │         │    ├── columns: j:3
 │         │    ├── immutable
 │         │    ├── stats: [rows=333.3333]
 │         │    ├── cost: 1068.35
 │         │    ├── scan a@j
 │         │    │    ├── columns: j:3
 │         │    │    ├── stats: [rows=1000]
 │         │    │    └── cost: 1058.32
 │         │    └── filters
 │         │         └── (j:3 + 1) IS NOT NULL [outer=(3), immutable]
 │         └── projections
 │              └── j:3 + 1 [as=column6:6, outer=(3), immutable]
 └── aggregations
      └── const-agg [as=min:7, outer=(6)]
           └── column6:6

# TopK has a higher cost than using a min aggregate when there are no NULLs.
opt
SELECT min(j+1) FROM b
----
scalar-group-by
 ├── columns: min:7
 ├── cardinality: [1 - 1]
 ├── immutable
 ├── stats: [rows=1]
 ├── cost: 1088.37
 ├── key: ()
 ├── fd: ()-->(7)
 ├── project
 │    ├── columns: column6:6!null
 │    ├── immutable
 │    ├── stats: [rows=1000]
 │    ├── cost: 1078.34
 │    ├── scan b@j
 │    │    ├── columns: j:3!null
 │    │    ├── stats: [rows=1000]
 │    │    └── cost: 1058.32
 │    └── projections
 │         └── j:3 + 1 [as=column6:6, outer=(3), immutable]
 └── aggregations
      └── min [as=min:7, outer=(6)]
           └── column6:6

exec-ddl
ALTER TABLE a INJECT STATISTICS '[
  {
    "columns": ["j"],
    "created_at": "2019-02-08 04:10:40.001179+00:00",
    "row_count": 10000,
    "distinct_count": 1000
  }
]'
----

# A partially ordered top-k has the lowest cost and propagates limit hints.
opt
SELECT * FROM a ORDER BY j, i LIMIT 10
----
top-k
 ├── columns: k:1!null i:2 j:3
 ├── internal-ordering: +3,+2
 ├── k: 10
 ├── cardinality: [0 - 10]
 ├── stats: [rows=10, distinct(3)=9.95512, null(3)=0]
 ├── cost: 7809.20825
 ├── key: (1)
 ├── fd: (1)-->(2,3)
 ├── ordering: +3,+2
 └── index-join a
      ├── columns: k:1!null i:2 j:3
      ├── stats: [rows=10000]
      ├── cost: 7717.72858
      ├── key: (1)
      ├── fd: (1)-->(2,3)
      ├── ordering: +3
      ├── limit hint: 1004.51
      └── scan a@j
           ├── columns: k:1!null j:3
           ├── stats: [rows=10000]
           ├── cost: 1062.70858
           ├── key: (1)
           ├── fd: (1)-->(3)
           ├── ordering: +3
           └── limit hint: 1004.51

# Inject stats corresponding to running:
# INSERT INTO a VALUES (1, 1, 1);
#
# These stats are important for the test below, which tests that the cost for
# top-k is non-negative when it has no input rows.
exec-ddl
ALTER TABLE a INJECT STATISTICS '[
    {
        "columns": [
            "k"
        ],
        "created_at": "2021-08-25 14:20:18.273949",
        "distinct_count": 1,
        "histo_buckets": [
            {
                "distinct_range": 0,
                "num_eq": 1,
                "num_range": 0,
                "upper_bound": "1"
            }
        ],
        "histo_col_type": "INT8",
        "name": "foo",
        "null_count": 0,
        "row_count": 1
    },
    {
        "columns": [
            "i"
        ],
        "created_at": "2021-08-25 14:20:18.273949",
        "distinct_count": 1,
        "histo_buckets": [
            {
                "distinct_range": 0,
                "num_eq": 1,
                "num_range": 0,
                "upper_bound": "1"
            }
        ],
        "histo_col_type": "INT8",
        "name": "foo",
        "null_count": 0,
        "row_count": 1
    },
    {
        "columns": [
            "j"
        ],
        "created_at": "2021-08-25 14:20:18.273949",
        "distinct_count": 1,
        "histo_buckets": [
            {
                "distinct_range": 0,
                "num_eq": 1,
                "num_range": 0,
                "upper_bound": "1"
            }
        ],
        "histo_col_type": "INT8",
        "name": "foo",
        "null_count": 0,
        "row_count": 1
    }
]'
----

# Based on the stats above, the subquery results in no output rows. The cost for
# top-k should be non-negative.
opt
SELECT * FROM (SELECT * FROM a WHERE k > 10) ORDER BY i LIMIT 1
----
top-k
 ├── columns: k:1!null i:2 j:3
 ├── internal-ordering: +2
 ├── k: 1
 ├── cardinality: [0 - 1]
 ├── stats: [rows=2e-10]
 ├── cost: 18.03
 ├── key: ()
 ├── fd: ()-->(1-3)
 └── scan a
      ├── columns: k:1!null i:2 j:3
      ├── constraint: /1: [/11 - ]
      ├── stats: [rows=2e-10, distinct(1)=2e-10, null(1)=0]
      │   histogram(1)=
      ├── cost: 18.02
      ├── key: (1)
      └── fd: (1)-->(2,3)
