Inconsistent null handling during explicit casting from numbers to string
Describe the bug
There appears to be inconsistencies in casting from numbers to string.
I'm using CastLongToStrFunctionFactory to illustrate the problem, but there is the same issue in CastIntToStrFunctionFactory and I assume also in other casting function factories.
Behaviour I - Constants When an upstream long function is a constant then the factory does not do any null check on its own:
public Function newInstance(int position, ObjList<Function> args, IntList argPositions, CairoConfiguration configuration, SqlExecutionContext sqlExecutionContext) {
Function func = args.getQuick(0);
if (func.isConstant()) {
StringSink sink = Misc.getThreadLocalBuilder();
sink.put(func.getLong(null));
return new StrConstant(Chars.toString(sink));
}
[...]When the constant value happens to be Long.MIN_VALUE then sink.put(Long.MIN_VALUE) writes "NaN" into the sink and this string is than used as the outcome of casting.
Behaviour II - Vars When the upstream function is not a constant then it's handled differently:
@Override
public CharSequence getStr(Record rec) {
final long value = arg.getLong(rec);
if (value == Numbers.LONG_NaN) {
return null;
}
sinkA.clear();
sinkA.put(value);
return sinkA;
}Numbers.LONG_NaN also happens to be Long.MIN_VALUE, but in this case, the casting function will produce null.
The different behaviour can be seen on a web console:
create table x (l long);
insert into x values (9223372036854775807L); -- LONG.MIN_VALUE - 1
select cast (l + 1 as string) as casting_var, cast (9223372036854775807L + 1 as string) as casting_const from x;
This behaviour looks accidental to me. Thus, it's probably a bug.
Source: questdb/questdb