type query = (*| Select of column list * table list option * filter option*) | Select of column list * table_expression | CreateSchema of string | CreateTable of table | DropSchema of string | DropTable of table and column = | Asterisk (* | Column of string *) | Column of expression * as_clause option and as_clause = | As of string and table_expression = | TableExpression of table list option * filter option * group option 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 predicand | NotLike of predicand and operator = | Equals | NotEquals | LessThan | GreaterThan | LessEquals | GreaterEquals and filter = condition and group = | Group of quantifier option * expression list option 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 | Select(cols, table_exp) -> Format.fprintf fmt "%s" (String.cat "SELECT " (pp_columns cols) ^ pp_table_expression table_exp) | _ -> failwith "not yet supported" 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(exp,_) -> pp_expression exp | Asterisk -> "*" and pp_expression exp = match exp with | Ref(name) -> name | StringLiteral(name) -> "'"^name^"'" | DateLiteral(name) -> "'"^name^"'" | TimeLiteral(name) -> "'"^name^"'" and pp_table_expression table_exp = match table_exp with | TableExpression(tables, filter, _) -> pp_tables tables ^ pp_filter filter and pp_tables tables = let rec aux t = match t with | [] -> "" | table::[] -> pp_table table | table::l -> pp_table table ^ ", " ^ aux l in match tables with | None -> "" | Some(t) -> " FROM " ^ aux t 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" and pp_filter filter = let rec aux f = match f with | Condition(exp, pred) -> pp_expression exp ^ " " ^ pp_predicate pred | And(c1, c2) -> aux c1 ^ " AND " ^ aux c2 | Or(c1, c2) -> aux c1 ^ " OR " ^ aux c2 | Not(c) -> "NOT" ^ aux c in match filter with | None -> "" | Some(f) -> " WHERE " ^ aux f and pp_predicate pred = match pred with | Comparison(op, exp) -> pp_operator op ^ pp_expression exp | Between(exp1, exp2) -> "BETWEEN " ^ pp_expression exp1 ^ " AND " ^pp_expression exp2 | NotBetween(exp1, exp2) -> "NOT BETWEEN " ^ pp_expression exp1 ^ " AND " ^pp_expression exp2 | Like(exp) -> "LIKE " ^ pp_expression exp | NotLike(exp) -> " NOT LIKE " ^ pp_expression exp | _ -> failwith "Predicate not supported" and pp_operator op = match op with | Equals -> "=" | NotEquals -> "!=" | LessThan -> "<" | GreaterThan -> ">" | LessEquals -> "<=" | GreaterEquals -> ">="