Almost for fun, I did this little experiment: take the output of an EXPLAIN from sql, and execute it in MAL (mclient -l mal).

I found only *1* detail which doesn't parse, here it is in a minimal example:

* Got the explain of a trivial query:

sql>\f raw
sql>explain select name from sys.functions;
% .explain # table_name
% mal # name
% clob # type
% 94 # length
function user.s4_1():void;
    X_32:void := querylog.define("explain select name from sys.functions;","default_pipe",21);
    X_16 := bat.new(nil:oid,nil:str);
    X_24 := bat.append(X_16,"sys.functions");
    X_19 := bat.new(nil:oid,nil:str);
    X_26 := bat.append(X_19,"name");
    X_20 := bat.new(nil:oid,nil:str);
    X_27 := bat.append(X_20,"varchar");
    X_21 := bat.new(nil:oid,nil:int);
    X_29 := bat.append(X_21,256);
    X_23 := bat.new(nil:oid,nil:int);
    X_31 := bat.append(X_23,0);
    X_1 := sql.mvc();
    C_2:bat[:oid] := sql.tid(X_1,"sys","functions");
    X_5:bat[:str] := sql.bind(X_1,"sys","functions","name",0);
    (C_8,r1_8) := sql.bind(X_1,"sys","functions","name",2);
    X_11:bat[:str] := sql.bind(X_1,"sys","functions","name",1);
    X_13 := sql.delta(X_5,C_8,r1_8,X_11);
    X_14 := algebra.projection(C_2,X_13);
    sql.resultSet(X_24,X_26,X_27,X_29,X_31,X_14);
end user.s4_1;
# optimizer.mitosis()
# optimizer.dataflow()


* Opened a MAL session, initialized sql, and pasted the function above:

mal>sql.init();
mal>function user.s4_1():void;
mal>    X_32:void := querylog.define("explain select name from sys.functions;","default_pipe",21);
mal>    X_16 := bat.new(nil:oid,nil:str);
mal>    X_24 := bat.append(X_16,"sys.functions");
mal>    X_19 := bat.new(nil:oid,nil:str);
mal>    X_26 := bat.append(X_19,"name");
mal>    X_20 := bat.new(nil:oid,nil:str);
mal>    X_27 := bat.append(X_20,"varchar");
mal>    X_21 := bat.new(nil:oid,nil:int);
mal>    X_29 := bat.append(X_21,256);
mal>    X_23 := bat.new(nil:oid,nil:int);
mal>    X_31 := bat.append(X_23,0);
mal>    X_1 := sql.mvc();
mal>    C_2:bat[:oid] := sql.tid(X_1,"sys","functions");
mal>    X_5:bat[:str] := sql.bind(X_1,"sys","functions","name",0);
mal>    (C_8,r1_8) := sql.bind(X_1,"sys","functions","name",2);
mal>    X_11:bat[:str] := sql.bind(X_1,"sys","functions","name",1);
mal>    X_13 := sql.delta(X_5,C_8,r1_8,X_11);
mal>    X_14 := algebra.projection(C_2,X_13);
mal>    sql.resultSet(X_24,X_26,X_27,X_29,X_31,X_14);
mal>end user.s4_1;
MAPI  = (monetdb) /tmp/.s.monetdb.54500
QUERY = end user.s4_1;
ERROR = !TypeException:user.s4_1[17]:'sql.delta' undefined in:     X_13:any := sql.delta(X_5:bat[:str],C_8:bat[:oid],r1_8:bat[:any],X_11:bat[:str]);
mal>

The error is easy to find: sql.delta() expects r1_8 to be of type :bat[:str], but it gets :bat[:any] instead. 


* If I fix it manually:

mal>function user.s4_1():void;
mal>    X_32:void := querylog.define("explain select name from sys.functions;","default_pipe",21);
mal>    X_16 := bat.new(nil:oid,nil:str);
mal>    X_24 := bat.append(X_16,"sys.functions");
mal>    X_19 := bat.new(nil:oid,nil:str);
mal>    X_26 := bat.append(X_19,"name");
mal>    X_20 := bat.new(nil:oid,nil:str);
mal>    X_27 := bat.append(X_20,"varchar");
mal>    X_21 := bat.new(nil:oid,nil:int);
mal>    X_29 := bat.append(X_21,256);
mal>    X_23 := bat.new(nil:oid,nil:int);
mal>    X_31 := bat.append(X_23,0);
mal>    X_1 := sql.mvc();
mal>    C_2:bat[:oid] := sql.tid(X_1,"sys","functions");
mal>    X_5:bat[:str] := sql.bind(X_1,"sys","functions","name",0);
mal>    (C_8,r1_8:bat[:str]) := sql.bind(X_1,"sys","functions","name",2);
mal>    X_11:bat[:str] := sql.bind(X_1,"sys","functions","name",1);
mal>    X_13 := sql.delta(X_5,C_8,r1_8,X_11);
mal>    X_14 := algebra.projection(C_2,X_13);
mal>    sql.resultSet(X_24,X_26,X_27,X_29,X_31,X_14);
mal>end user.s4_1;
mal>

Yay, it works.


* The reason I write this email:
- I suspect that the output of EXPLAIN is not meant to necessarily be re-parsable, but just to be informative
- Nevertheless, it really is almost re-parsable. I tried a much larger query, (2000+ lines of MAL), and this was the only detail. It looks like fixing that small detail could be worth it.
- Also, I wonder if this is, in fact, a bug. Binds to access types 0 and 1 do get the right type information. Why not access type 2?