@@ -479,7 +479,7 @@ suite("topk_min_max_count") {
479479 }
480480
481481 // A NULL counter is invalid SQL input and must be a query error; a checked invariant would
482- // terminate a debugging BE.
482+ // terminate a debugging BE. Cover every counter on both MIN and MAX.
483483 test {
484484 sql """ SELECT topk_merge_min(
485485 CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
@@ -493,7 +493,7 @@ suite("topk_min_max_count") {
493493 }
494494
495495 test {
496- sql """ SELECT topk_merge_max (
496+ sql """ SELECT topk_merge_min (
497497 CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
498498 CAST(NULL AS INT),
499499 CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
@@ -516,6 +516,94 @@ suite("topk_min_max_count") {
516516 exception " k must not be NULL"
517517 }
518518
519+ test {
520+ sql """ SELECT topk_merge_max(
521+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
522+ CAST(NULL AS INT),
523+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
524+ CAST(NULL AS INT),
525+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
526+ CAST(NULL AS INT),
527+ CAST(NULL AS BIGINT), 0, 2)"""
528+ exception " n must not be NULL"
529+ }
530+
531+ test {
532+ sql """ SELECT topk_merge_max(
533+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
534+ CAST(NULL AS INT),
535+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
536+ CAST(NULL AS INT),
537+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
538+ CAST(NULL AS INT),
539+ 0, CAST(NULL AS BIGINT), 2)"""
540+ exception " dn must not be NULL"
541+ }
542+
543+ test {
544+ sql """ SELECT topk_merge_max(
545+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
546+ CAST(NULL AS INT),
547+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
548+ CAST(NULL AS INT),
549+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
550+ CAST(NULL AS INT),
551+ 0, 0, CAST(NULL AS BIGINT))"""
552+ exception " k must not be NULL"
553+ }
554+
555+ // The counters can also arrive as nullable table columns instead of NULL literals.
556+ sql """ DROP TABLE IF EXISTS topk_merge_null_t"""
557+ sql """
558+ CREATE TABLE topk_merge_null_t (
559+ row_id INT,
560+ n BIGINT,
561+ dn BIGINT,
562+ k BIGINT
563+ )
564+ DISTRIBUTED BY HASH(row_id) BUCKETS 1
565+ PROPERTIES ("replication_num" = "1")
566+ """
567+ sql """ INSERT INTO topk_merge_null_t VALUES (0, NULL, 0, 2), (1, 0, NULL, 2), (2, 0, 0, NULL)"""
568+ test {
569+ sql """ SELECT topk_merge_min(
570+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
571+ CAST(NULL AS INT),
572+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
573+ CAST(NULL AS INT),
574+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
575+ CAST(NULL AS INT),
576+ n, dn, k)
577+ FROM topk_merge_null_t WHERE row_id = 0"""
578+ exception " n must not be NULL"
579+ }
580+
581+ test {
582+ sql """ SELECT topk_merge_min(
583+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
584+ CAST(NULL AS INT),
585+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
586+ CAST(NULL AS INT),
587+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
588+ CAST(NULL AS INT),
589+ n, dn, k)
590+ FROM topk_merge_null_t WHERE row_id = 1"""
591+ exception " dn must not be NULL"
592+ }
593+
594+ test {
595+ sql """ SELECT topk_merge_min(
596+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
597+ CAST(NULL AS INT),
598+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
599+ CAST(NULL AS INT),
600+ CAST(array() AS ARRAY<STRUCT<value:INT, count:BIGINT>>),
601+ CAST(NULL AS INT),
602+ n, dn, k)
603+ FROM topk_merge_null_t WHERE row_id = 2"""
604+ exception " k must not be NULL"
605+ }
606+
519607 // A cancel pair can exceed int64 in an intermediate while the final count still fits.
520608 order_qt_merge_min_cancel_at_int64_max """
521609 SELECT topk_merge_min(
0 commit comments