Só com um pouco de esforço. Algo assim:
select listagg((case when running_len < 4000 then oi.impression end), ',') within group (order by oi.line)
from (select oi.*,
sum(length(oi.impression) + 1) over (partition by ?? order by oi.line) as running_len
from order_impression oi
) oi
group by ??;
Isso calcula o comprimento de corrida e agrega apenas os valores que não excedem o comprimento. O
??
é o que você está usando para agregação. Isso pressupõe que line
é único, então o order by
é estável. Isso não incluirá a
impression
que excede o comprimento - e nada depois disso. Não corta a impressão. Essa lógica é possível, mas complica a consulta.