let rec make_pp_query (e, ol) =
  Valign ((make_pp_query_exp e)::
            if ol = [] then []
            else [Halign (r "ORDER BY"
                         :: (list_between make_pp_ordering (r ",") ol))])
and make_pp_ordering (c, tri) =
  Halign  ((match c with `numcolumn i -> r (string_of_int i) | `column c -> make_pp_column c)
          :: (match tri with None -> [] | Some `asc -> [r "ASC"| Some `desc -> [r "DESC"]))
and make_pp_column = function
    `ref s -> r s
  | `refdotref (s1, s2) -> r (sprintf "%s.%s" s1 s2)
and make_pp_query_exp = function
    `select select -> make_pp_select select
  | `union (qe1, qe2) -> Valign [ make_pp_query_exp qe1 ; r "UNION" ; make_pp_query_exp qe2 ]
  | `unionall (qe1, qe2) -> Valign [ make_pp_query_exp qe1 ; r "UNION ALL" ; make_pp_query_exp qe2 ]
and make_pp_select ((md, sel, from, where, grp, hav):Sqml_sqlstx.select) =
  Block (List.flatten [
           [ Halign (List.flatten [
                       [r "SELECT"];
                       (match md with `nomod -> [] | `all -> [r "ALL"| `distinct -> [r "DISTINCT"]);
                       [make_pp_selection sel; r "FROM"; make_pp_from from]]) ];
         (match where with None -> [] | Some cond -> [Halign [r "WHERE"Indent (make_pp_condition cond)]]);
         (match grp with None -> [] | Some groupby -> [Halign [r "GROUP BY"; make_pp_groupby groupby]]);
         (match hav with None -> [] | Some cond -> [Halign [r "HAVING"; make_pp_condition cond]])
         ])
and make_pp_selection = function
    `star -> r "*"
  | `list l -> Halign (list_between make_pp_exp (r ",") l)
and make_pp_from l =
  Halign (list_between (function
                            `table t -> r t
                          | `tableas (t, a) -> Halign [r t; r "AS"; r a]) (r ",") l)
and make_pp_groupby l =
  Halign (list_between make_pp_column (r ",") l)
and make_pp_condition = function
    `cand (c1, c2) -> Halign [r "("; make_pp_condition c1; r "AND"; make_pp_condition c2; r ")"]
  | `cor (c1, c2) -> Halign [r "("Valign [Indent (make_pp_condition c1);
                                            Halign [r "OR"Indent (make_pp_condition c2)]]
                            ; r ")"]
  | `cnot c -> Halign [r "NOT"; make_pp_condition c]
  | `p p -> make_pp_pred p
and make_pp_pred = function
    `comparisonexp (exp1 , comparison , exp2) -> Halign [make_pp_exp exp1; make_pp_comp comparison; make_pp_exp exp2]
  | `comparisonselect (exp , comparison , select )-> Halign [make_pp_exp exp; make_pp_comp comparison; r "("; make_pp_select select; r ")"]
  | `between (bool , exp1 , exp2 , exp3) ->
      Halign [make_pp_exp exp1; if bool then r "NOT BETWEEN" else r "BETWEEN"; make_pp_exp exp2; r "AND"; make_pp_exp exp3]
  | `like (bool , exp , atom , atopt) ->
      Halign [make_pp_exp exp; if bool then r "NOT LIKE" else r "LIKE"; make_pp_atom atom;
              (match atopt with None -> r "" | Some atom -> Halign [r "ESCAPE"; make_pp_atom atom])]
  | `iscolnull (bool , column) ->
      Halign [make_pp_column column; if bool then r "IS NOT NULL" else r "IS NULL"]
  | `in_select (bool , exp , select) ->
      Halign [make_pp_exp exp; if bool then r "NOT IN" else r "IN"; make_pp_select select]
  | `in_atom_list (bool , exp , atl) ->
      Halign [make_pp_exp exp; r "IN"; r "("Halign (list_between make_pp_atom (r ",") atl); r ")"]
  | `allorany (exp , comparison , allsome , select) ->
      Halign [make_pp_exp exp; make_pp_comp comparison;
              (match allsome with `all -> r "ALL" | `some -> r "SOME");
              make_pp_select select]
  | `exists select -> Halign [ r "EXISTS"; make_pp_select select]
and make_pp_comp = function
  | `eq -> r "="
  | `neq -> r "<>"
  | `lt -> r "<"
  | `gt -> r ">"
  | `lte -> r "<="
  | `gte -> r ">="
and make_pp_exp = function
    `binop (pmtd , exp1 , exp2) ->
      Halign [r "("; make_pp_exp exp1;
              (match pmtd with
                 `plus -> r "+"
               | `minus -> r "-"
               | `times -> r "*"
               | `div -> r "/");
              make_pp_exp exp2; r ")"]
  | `uminus exp -> Halign [r "-"; make_pp_exp exp]
  | `atom atom -> make_pp_atom atom
  | `column column -> make_pp_column column
  | `functioncall functioncall -> make_pp_functioncall functioncall
and make_pp_atom = function
    `parameter parameter -> make_pp_parameter parameter
  | `string string -> r (sqlquote string)
  | `int int -> r (string_of_int int)
  | `inttoomuch string -> r string
  | `float (int1 , int2 , float) -> r (sprintf "%*.*f" int1 int2 float)
  | `floattoomuch string -> r string
  | `user -> r "USER"
and make_pp_functioncall (function_label , x) =
        Halign [ r ((string_of_function_label function_label)^"(");
                 (match x with
                    `star -> r " * )"
                  | `distinct column -> Halign [ r "DISTINCT"; make_pp_column column; r ")" ]
                  | `exp (`nomod , exp) -> Halign [  make_pp_exp exp ; r ")" ]
                  | `exp (`all, exp) -> Halign [  r "ALL"; make_pp_exp exp ; r ")" ]
                 );]
and string_of_function_label = function
    `min -> "MIN"
  | `max -> "MAX"
  | `sum -> "SUM"
  | `count -> "COUNT"
  | `avg -> "AVG"
  | `other string -> string
and make_pp_parameter = function
    `single string -> Var string
  | `single_annotated (string, _, _) -> Var string
  | `couple (string , string2) -> failwith "I don't know what double parameters mean"
  | `indicator (string , string2) -> failwith "I don't know what indicator parameters mean"