anchor.diff:          {ok, {[{ParseTree,_}|_], Tokens}} -> 
               if ShowParseTree ->
           	    io:format(user, "~p~n", [ParseTree]),
  -                NSql = foldi(ParseTree),
  +                {NSql, _} = foldi(ParseTree),
                   io:format(user,  "~n> " ++ NSql ++ "~n", []),
                   {ok, {[{NPTree,_}|_], NToks}} = sqlparse:parsetree(NSql),
                   try
  
positive.code: -export([init/1]).
  
  % parser and compiler interface
  -export([fold/1, parsetree/1, is_reserved/1]).
  
  -ifdef(TEST).
  % eunit helper function
  
negative.code: %
  % SELECT
  %
  foldi({select, Opts} = ST, Fun, Ctx)
   when is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      {NewOs, NewCtx1} = lists:foldl(fun(O, {Acc, CtxAcc}) ->
              {SubAcc, CtxAcc1} = foldi(O, Fun, CtxAcc),
              {Acc++[SubAcc], CtxAcc1}
          end,
          {[], NewCtx},
          Opts),
      {"select "++lists:flatten(NewOs), NewCtx1};
  
  %
  % INSERT
  %
  foldi({insert, Tab, {cols, Cols}, {values, Values}, Return} = ST, Fun, Ctx)
   when is_binary(Tab), is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      {CStrs, NewCtx1} = lists:foldl(fun(C, {Acc, CtxAcc}) ->
              case C of
                  C when is_binary(C) ->
                      {Acc++[binary_to_list(C)], Fun(C, CtxAcc)};
                  C ->
                      {CT, CtxAcc1} = foldi(C, Fun, CtxAcc),
                      {Acc++[CT], CtxAcc1}
              end
          end,
          {[], NewCtx},
          Cols),
      {Vals, NewCtx2} = lists:foldl(fun(V, {Acc1, CtxAcc1}) ->
              case V of
                  V when is_binary(V) ->
                      {Acc1++[binary_to_list(V)], Fun(V, CtxAcc1)};
                  V ->
                      {VT, CtxAcc2} = foldi(V, Fun, CtxAcc1),
                      {Acc1++[VT], CtxAcc2}
              end
          end,
          {[], NewCtx1},
          Values),
      {Ret, NewCtx3} = foldi(Return, Fun, NewCtx2),
      {"insert into " ++ binary_to_list(Tab) ++
       case length(CStrs) of
           0 -> "";
           _ -> lists:flatten(["(", string:join(CStrs, ","), ")"])
       end ++ " values (" ++ string:join(Vals, ",") ++ ")" ++ Ret
      , NewCtx3};
  
  %
  % CREATE TABLE
  %
  foldi({'create table', Tab, Fields, Opts} = ST, Fun, Ctx)
   when is_binary(Tab), is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      {OptsStr, NewCtx1} = foldi(Opts, Fun, NewCtx),
      NewCtx2 = Fun(Tab, NewCtx1),
      {Clms, NewCtx3} = lists:foldl(fun(Clm, {Acc, CtxAcc}) ->
              case Clm of
                  {C, {T, N}, O} when is_binary(C) ->
                      CtxAcc1 = Fun(C, CtxAcc),
                      CtxAcc2 = Fun(T, CtxAcc1),
                      CtxAcc3 = Fun(N, CtxAcc2),
                      {SubAcc, CtxAcc4} = foldi(O, Fun, CtxAcc3),
                      {Acc ++ [lists:flatten([binary_to_list(C), " ", atom_to_list(T), "(", N, ") ", SubAcc])]
                      , CtxAcc4};
                  {C, {T, N, N1}, O} when is_binary(C) ->
                      CtxAcc1 = Fun(C, CtxAcc),
                      CtxAcc2 = Fun(T, CtxAcc1),
                      CtxAcc3 = Fun(N, CtxAcc2),
                      CtxAcc4 = Fun(N1, CtxAcc3),
                      {SubAcc, CtxAcc5} = foldi(O, Fun, CtxAcc4),
                      {Acc ++ [lists:flatten([binary_to_list(C), " ", atom_to_list(T), "(",N,",",N1,") ", SubAcc])]
                      , CtxAcc5};
                  {C, T, O} when is_binary(C) and is_binary(T) ->
                      CtxAcc1 = Fun(C, CtxAcc),
                      CtxAcc2 = Fun(T, CtxAcc1),
                      {SubAcc, CtxAcc3} = foldi(O, Fun, CtxAcc2),
                      {Acc ++ [lists:flatten([binary_to_list(C), " ", binary_to_list(T), " ", SubAcc])]
                      , CtxAcc3};
                  {C, T, O} when is_binary(C) ->
                      CtxAcc1 = Fun(C, CtxAcc),
                      CtxAcc2 = Fun(T, CtxAcc1),
                      {SubAcc, CtxAcc3} = foldi(O, Fun, CtxAcc2),
                      {Acc ++ [lists:flatten([binary_to_list(C), " ", atom_to_list(T), " ", SubAcc])]
                      , CtxAcc3};
                  Clm ->
                      {SubAcc, CtxAcc1} = foldi(Clm, Fun, CtxAcc),
                      {Acc++[SubAcc], CtxAcc1}
              end
          end,
          {[], NewCtx2},
          Fields),
      {"create " ++ OptsStr ++ " table " ++ binary_to_list(Tab)
          ++ " (" ++ string:join(Clms, ", ") ++ ")"
      , NewCtx3};
  
  %
  % CREATE USER
  %
  foldi({'create user', Usr, Id, Opts} = ST, Fun, Ctx)
   when is_binary(Usr), is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      NewCtx1 = Fun(Usr, NewCtx),
      {IdStr, NewCtx2} = foldi(Id, Fun, NewCtx1),
      {OptsStr, NewCtx3} = foldi(Opts, Fun, NewCtx2),
      {"create user " ++ binary_to_list(Usr)
      ++ IdStr ++ " " ++ OptsStr
      , NewCtx3};
  
  %
  % ALTER USER
  %
  foldi({'alter user', Usr, {spec, Opts}} = ST, Fun, Ctx)
   when is_binary(Usr), is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      NewCtx1 = Fun(Usr, NewCtx),
      {OptsStr, NewCtx2} = foldi(Opts, Fun, NewCtx1),
      {lists:flatten(["alter user ", binary_to_list(Usr), " ", OptsStr])
      , NewCtx2};
  
  %
  % TRUNCATE TABLE
  %
  foldi({'truncate table', Tbl, Mvl, Storage} = ST, Fun, Ctx)
   when is_binary(Tbl), is_function(Fun, 2) ->
      NewCtx = Fun(ST, Ctx),
      NewCtx1 = Fun(Tbl, NewCtx),
      NewCtx2 = Fun(Mvl, NewCtx1),
      NewCtx3 = Fun(Storage, NewCtx2),
      {"truncate table " ++ binary_to_list(Tbl) ++ " " ++
      case Mvl of
          {} -> "";
          {'materialized view log', T} -> lists:flatten([atom_to_list(T), " materialized view log "])
  