Looking at BufferedPlanRootSink and SpillableRowBatchQueue, it seems the code fail to anticipate if max_spilled_result_spooling_mem = 0 (unbounded). max_unpinned_bytes_ will be set to 0 and SpillableRowBatchQueue::IsFull() will always be true. We should change max_unpinned_bytes_ to INT64_MAX if max_spilled_result_spooling_mem = 0.
Another bug happen when setting max_result_spooling_mem = 0 (unbounded). When this happen, PlanRootSink.java will peg maxMemReservationBytes to always equal to minMemReservationBytes. I think we should override it to the default max_result_spooling_mem (100MB) or set it equal to mem_limit of the query pool.