type query = | Select of column list * table_expression | CreateSchema of string | CreateTable of table_scope option * table | DropSchema of string | DropTable of table | DropColumn of string and table_scope = | Global | Local and column = | Asterisk | Column of expression_primary * 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 expression_primary * predicate | And of condition * condition | Or of condition * condition | Not of condition and predicate = | Comparison of operator * expression_primary | Between of expression_primary * expression_primary | NotBetween of expression_primary * expression_primary | In of expression_primary list | NotIn of expression_primary list | Like of expression_primary | NotLike of expression_primary and operator = | Equals | NotEquals | LessThan | GreaterThan | LessEquals | GreaterEquals and filter = condition and group = | Group of quantifier option * expression_primary list option and aggregate = | Aggregate of func * filter option and func = | Function of function_type * quantifier option * expression_primary and function_type = | Avg | Max | Min | Sum | Count and quantifier = | All | Distinct and expression_primary = | Ref of string | StringLiteral of string | DateLiteral of string | TimeLiteral of string | TimestampLiteral of string | IntegerLiteral of int | FloatLiteral of float | Concatenation of expression_primary * expression_primary | Numeric of expression_primary * sign * expression_primary | Signed of sign * expression_primary | Substring of expression_primary * expression_primary and sign = | Plus | Minus | Times | Divide 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(s) -> "'" ^ s ^ "'" | DateLiteral(d) -> "'" ^ d ^ "'" | TimeLiteral(t) -> "'" ^ t ^ "'" | TimestampLiteral(ts) -> "'" ^ ts ^ "'" | IntegerLiteral(i) -> string_of_int i | FloatLiteral(f) -> string_of_float f | Numeric(n1, s, n2) -> pp_expression n1 ^ pp_sign s ^ pp_expression n2 | _ -> "Expression not yet supported" and pp_sign sign = match sign with | Plus -> "+" | Minus -> "-" | Times -> "*" | Divide -> "/" 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 -> ">="