type query = Query of select_stmt and select_stmt = | Select of column list * table list option * filter option and column = | Asterisk (* | Column of string *) | Column of expression * as_clause option and as_clause = | As of string and table = | Table of string | Join of table * join_type * table * condition option and join_type = | Inner | Left | Right | Full | Cross | Union | Natural and condition = | Condition of predicand * predicate | And of condition * condition | Or of condition * condition | Not of condition and predicand = expression and predicate = | Comparison of operator * predicand | Between of predicand * predicand | NotBetween of predicand * predicand | In of predicand list | NotIn of predicand list | Like of string | NotLike of string and operator = | Equals | NotEquals | LessThan | GreaterThan | LessEquals | GreaterEquals and filter = | Filter of condition and aggregate = | Aggregate of func * filter option and func = | Function of function_type * quantifier option * expression and function_type = | Avg | Max | Min | Sum | Count and quantifier = | All | Distinct and expression = | Ref of string | StringLiteral of string | DateLiteral of string | TimeLiteral of string let rec pp_query fmt ast = match ast with | Query(s) -> Format.fprintf fmt "%s" (pp_select s) and pp_select s = match s with | Select(cols, _, _) -> String.cat "SELECT " (pp_columns cols) and pp_columns cols = match cols with | [] -> "" | [col] -> pp_column col | col::l -> pp_column col ^ ";" ^ pp_columns l and pp_column col = match col with | Column(Ref(name),_) -> name | Column(StringLiteral(name),_) -> "'"^name^"'" | Column(DateLiteral(name),_) -> "'"^name^"'" | Asterisk -> "*" | _ -> failwith "Pretty parsing of Column not supported" and pp_tables tables = match tables with | [] -> "" | [table] -> pp_table table | table::l -> pp_table table ^ ";" ^ pp_tables l and pp_table table = match table with | Table(table) -> table | Join(t1, j, t2, _) -> pp_table t1 ^ pp_join_type j ^ pp_table t2 and pp_join_type j = match j with | Inner -> "inner" | Left -> "left" | Right -> "right" | Full -> "full" | Cross -> "cross" | Union -> "union" | Natural -> "natural"