This is the pretty printer code which takes AST values and turns them back into SQL source text. It attempts to format the output nicely. > module Pretty (prettyQueryExpr, prettyScalarExpr) where > import Syntax > import Text.PrettyPrint > import Data.Maybe > prettyQueryExpr :: QueryExpr -> String > prettyQueryExpr = render . queryExpr > prettyScalarExpr :: ScalarExpr -> String > prettyScalarExpr = render . scalarExpr = scalar expressions > scalarExpr :: ScalarExpr -> Doc > scalarExpr (Literal s) = quotes $ text s > scalarExpr (Identifier i) = text i > scalarExpr (Identifier2 q i) = text q <> text "." <> text i > scalarExpr Star = text "*" > scalarExpr (Star2 q) = text q <> text "." <> text "*" > scalarExpr (App f es) = text f <> parens (commaSep (map scalarExpr es)) > scalarExpr (Op f [e]) = text f <+> scalarExpr e > scalarExpr (Op f [e0,e1]) = > sep [scalarExpr e0, text f, scalarExpr e1] > scalarExpr (Op f es) = > -- TODO: how to handle this? error or either seems poor > text f <> parens (commaSep (map scalarExpr es)) > scalarExpr (Case t ws els) = > sep [text "case" <+> (maybe empty scalarExpr t) > ,nest 4 (sep ((map w ws) > ++ maybeToList (fmap e els))) > ,text "end"] > where > w (t0,t1) = sep [text "when" <+> scalarExpr t0 > ,text "then" <+> scalarExpr t1] > e el = text "else" <+> scalarExpr el > scalarExpr (Parens e) = parens $ scalarExpr e = query expressions > queryExpr :: QueryExpr -> Doc > queryExpr (Select sl fr wh gb hv od) = > sep [text "select" > ,nest 4 $ sep [selectList sl] > ,from fr > ,whr wh > ,grpBy gb > ,having hv > ,orderBy od] > selectList :: [(Maybe String, ScalarExpr)] -> Doc > selectList is = commaSep $ map si is > where > si (al,e) = scalarExpr e <+> maybe empty alias al > alias al = text "as" <+> text al > from :: [TableRef] -> Doc > from [] = empty > from ts = > sep [text "from" > ,nest 4 $ commaSep $ map tr ts] > where > tr (SimpleTableRef t) = text t > tr (JoinAlias t a) = tr t <+> text "as" <+> text a > tr (JoinParens t) = parens $ tr t > tr (JoinQueryExpr q) = parens $ queryExpr q > tr (JoinTableRef jt t0 t1 jc) = > sep [tr t0 > ,joinText jt jc > ,tr t1 > ,joinCond jc] > joinText jt jc = > sep [case jc of > Just JoinNatural -> text "natural" > _ -> empty > ,case jt of > Inner -> text "inner" > JLeft -> text "left" > JRight -> text "right" > Full -> text "full" > Cross -> text "cross" > ,text "join"] > joinCond (Just (JoinOn e)) = text "on" <+> scalarExpr e > joinCond (Just (JoinUsing es)) = text "using" <+> parens (commaSep $ map text es) > joinCond Nothing = empty > joinCond (Just JoinNatural) = empty > whr :: Maybe ScalarExpr -> Doc > whr = maybe empty > (\w -> sep [text "where" > ,nest 4 $ scalarExpr w]) > grpBy :: [ScalarExpr] -> Doc > grpBy [] = empty > grpBy gs = sep [text "group by" > ,nest 4 $ commaSep $ map scalarExpr gs] > having :: Maybe ScalarExpr -> Doc > having = maybe empty > (\w -> sep [text "having" > ,nest 4 $ scalarExpr w]) > orderBy :: [ScalarExpr] -> Doc > orderBy [] = empty > orderBy os = sep [text "order by" > ,nest 4 $ commaSep $ map scalarExpr os] = utils > commaSep :: [Doc] -> Doc > commaSep ds = sep $ punctuate comma ds