work on website
This commit is contained in:
parent
357c5737b6
commit
61e7a89416
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
/dist/
|
||||
/logchanges
|
||||
/cabal.sandbox.config
|
||||
/.cabal-sandbox/
|
||||
/.cabal-sandbox/
|
||||
/build/
|
||||
|
|
62
website/RenderTestCases.lhs
Normal file
62
website/RenderTestCases.lhs
Normal file
|
@ -0,0 +1,62 @@
|
|||
|
||||
Converts the test data to markdown
|
||||
|
||||
> import Language.SQL.SimpleSQL.Tests
|
||||
> import Text.Show.Pretty
|
||||
> import Control.Monad.State
|
||||
> import Language.SQL.SimpleSQL.Parser
|
||||
> import Language.SQL.SimpleSQL.Lexer
|
||||
|
||||
> data TableItem = Heading Int String
|
||||
> | Row String String
|
||||
|
||||
> doc :: Int -> TestItem -> [TableItem]
|
||||
> doc n (Group nm is) =
|
||||
> Heading n nm
|
||||
> : concatMap (doc (n + 1)) is
|
||||
> doc _ (TestValueExpr _ str e) =
|
||||
> [Row str (ppShow e)]
|
||||
> doc _ (TestQueryExpr _ str e) =
|
||||
> [Row str (ppShow e)]
|
||||
> doc _ (TestStatement _ str e) =
|
||||
> [Row str (ppShow e)]
|
||||
> doc _ (TestStatements _ str e) =
|
||||
> [Row str (ppShow e)]
|
||||
> doc _ (ParseQueryExpr d str) =
|
||||
> [Row str (ppShow $ parseQueryExpr d "" Nothing str)]
|
||||
> doc _ (ParseQueryExprFails d str) =
|
||||
> [Row str (ppShow $ parseQueryExpr d "" Nothing str)]
|
||||
> doc _ (ParseValueExprFails d str) =
|
||||
> [Row str (ppShow $ parseValueExpr d "" Nothing str)]
|
||||
|
||||
> doc _ (LexerTest d str t) =
|
||||
> -- todo: figure out how to handle this:
|
||||
> -- too many entries, but want to show the lexing
|
||||
> -- a bit
|
||||
> -- [Row str (ppShow $ lexSQL d "" Nothing str)]
|
||||
> []
|
||||
> -- should probably think about doing something similar
|
||||
> -- with other generated combination tests such as the typename
|
||||
> -- tests
|
||||
|
||||
TODO: should put the dialect in the html output
|
||||
|
||||
|
||||
> render :: [TableItem] -> IO ()
|
||||
> render = go False
|
||||
> where
|
||||
> go t (Heading level title : is) = do
|
||||
> when t $ putStrLn "</table>"
|
||||
> putStrLn $ replicate level '#' ++ " " ++ title
|
||||
> go False is
|
||||
> go t (Row sql hask : is) = do
|
||||
> unless t $ putStrLn "<table>"
|
||||
> let sql' = "\n~~~~{.sql}\n" ++ sql ++ "\n~~~~\n"
|
||||
> hask' = "\n~~~~{.haskell}\n" ++ hask ++ "\n~~~~\n"
|
||||
> putStrLn $ "<tr><td>" ++ sql'
|
||||
> ++ "</td><td>" ++ hask' ++ "</td></tr>"
|
||||
> go True is
|
||||
> go t [] = when t $ putStrLn "</table>"
|
||||
|
||||
> main :: IO ()
|
||||
> main = render $ doc 1 testData
|
416
website/index.txt
Normal file
416
website/index.txt
Normal file
|
@ -0,0 +1,416 @@
|
|||
# simple-sql-parser
|
||||
|
||||
A parser for SQL in Haskell. Also includes a pretty printer which
|
||||
formats output nicely. Current target is to parse most SQL:2011
|
||||
queries, plus a good subset of DDL, non-query DML, transaction
|
||||
management, access control and session management.
|
||||
|
||||
This is the documentation for version 0.5.0.
|
||||
|
||||
Status: Covers a lot of queries already, but the public API is
|
||||
probably not very stable, since adding support for all the
|
||||
not-yet-supported ANSI SQL syntax, then other dialects of SQL is
|
||||
likely to change the abstract syntax types considerably.
|
||||
|
||||
Tested with GHC 7.10.2, 7.8.4 and 7.6.3.
|
||||
|
||||
# Examples
|
||||
|
||||
Simple expression:
|
||||
|
||||
~~~~{.sql}
|
||||
select a + b * c
|
||||
~~~~
|
||||
|
||||
Parsed AST:
|
||||
|
||||
~~~~{.haskell}
|
||||
Select{qeSetQuantifier = All,
|
||||
qeSelectList =
|
||||
[(BinOp (Iden (Name "a")) (Name "+")
|
||||
(BinOp (Iden (Name "b")) (Name "*") (Iden (Name "c"))),
|
||||
Nothing)],
|
||||
qeFrom = [], qeWhere = Nothing, qeGroupBy = [], qeHaving = Nothing,
|
||||
qeOrderBy = [], qeOffset = Nothing, qeFetchFirst = Nothing}
|
||||
~~~~
|
||||
|
||||
TPC-H query 21:
|
||||
|
||||
~~~~{.sql}
|
||||
select
|
||||
s_name,
|
||||
count(*) as numwait
|
||||
from
|
||||
supplier,
|
||||
lineitem l1,
|
||||
orders,
|
||||
nation
|
||||
where
|
||||
s_suppkey = l1.l_suppkey
|
||||
and o_orderkey = l1.l_orderkey
|
||||
and o_orderstatus = 'F'
|
||||
and l1.l_receiptdate > l1.l_commitdate
|
||||
and exists (
|
||||
select
|
||||
*
|
||||
from
|
||||
lineitem l2
|
||||
where
|
||||
l2.l_orderkey = l1.l_orderkey
|
||||
and l2.l_suppkey <> l1.l_suppkey
|
||||
)
|
||||
and not exists (
|
||||
select
|
||||
*
|
||||
from
|
||||
lineitem l3
|
||||
where
|
||||
l3.l_orderkey = l1.l_orderkey
|
||||
and l3.l_suppkey <> l1.l_suppkey
|
||||
and l3.l_receiptdate > l3.l_commitdate
|
||||
)
|
||||
and s_nationkey = n_nationkey
|
||||
and n_name = 'INDIA'
|
||||
group by
|
||||
s_name
|
||||
order by
|
||||
numwait desc,
|
||||
s_name
|
||||
fetch first 100 rows only;
|
||||
~~~~
|
||||
|
||||
Parsed:
|
||||
|
||||
~~~~{.haskell}
|
||||
Select{qeSetQuantifier = All,
|
||||
qeSelectList =
|
||||
[(Iden (Name "s_name"), Nothing),
|
||||
(App (Name "count") [Star], Just (Name "numwait"))],
|
||||
qeFrom =
|
||||
[TRSimple (Name "supplier"),
|
||||
TRAlias (TRSimple (Name "lineitem")) (Alias (Name "l1") Nothing),
|
||||
TRSimple (Name "orders"), TRSimple (Name "nation")],
|
||||
qeWhere =
|
||||
Just
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "s_suppkey")) (Name "=")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_suppkey"))))
|
||||
(Name "and")
|
||||
(BinOp (Iden (Name "o_orderkey")) (Name "=")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_orderkey")))))
|
||||
(Name "and")
|
||||
(BinOp (Iden (Name "o_orderstatus")) (Name "=") (StringLit "F")))
|
||||
(Name "and")
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l1")) (Name ".") (Iden (Name "l_receiptdate")))
|
||||
(Name ">")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_commitdate")))))
|
||||
(Name "and")
|
||||
(SubQueryExpr SqExists
|
||||
(Select{qeSetQuantifier = All, qeSelectList = [(Star, Nothing)],
|
||||
qeFrom =
|
||||
[TRAlias (TRSimple (Name "lineitem"))
|
||||
(Alias (Name "l2") Nothing)],
|
||||
qeWhere =
|
||||
Just
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l2")) (Name ".")
|
||||
(Iden (Name "l_orderkey")))
|
||||
(Name "=")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_orderkey"))))
|
||||
(Name "and")
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l2")) (Name ".")
|
||||
(Iden (Name "l_suppkey")))
|
||||
(Name "<>")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_suppkey"))))),
|
||||
qeGroupBy = [], qeHaving = Nothing, qeOrderBy = [],
|
||||
qeOffset = Nothing, qeFetchFirst = Nothing})))
|
||||
(Name "and")
|
||||
(PrefixOp (Name "not")
|
||||
(SubQueryExpr SqExists
|
||||
(Select{qeSetQuantifier = All, qeSelectList = [(Star, Nothing)],
|
||||
qeFrom =
|
||||
[TRAlias (TRSimple (Name "lineitem"))
|
||||
(Alias (Name "l3") Nothing)],
|
||||
qeWhere =
|
||||
Just
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l3")) (Name ".")
|
||||
(Iden (Name "l_orderkey")))
|
||||
(Name "=")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_orderkey"))))
|
||||
(Name "and")
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l3")) (Name ".")
|
||||
(Iden (Name "l_suppkey")))
|
||||
(Name "<>")
|
||||
(BinOp (Iden (Name "l1")) (Name ".")
|
||||
(Iden (Name "l_suppkey")))))
|
||||
(Name "and")
|
||||
(BinOp
|
||||
(BinOp (Iden (Name "l3")) (Name ".")
|
||||
(Iden (Name "l_receiptdate")))
|
||||
(Name ">")
|
||||
(BinOp (Iden (Name "l3")) (Name ".")
|
||||
(Iden (Name "l_commitdate"))))),
|
||||
qeGroupBy = [], qeHaving = Nothing, qeOrderBy = [],
|
||||
qeOffset = Nothing, qeFetchFirst = Nothing}))))
|
||||
(Name "and")
|
||||
(BinOp (Iden (Name "s_nationkey")) (Name "=")
|
||||
(Iden (Name "n_nationkey"))))
|
||||
(Name "and")
|
||||
(BinOp (Iden (Name "n_name")) (Name "=") (StringLit "INDIA"))),
|
||||
qeGroupBy = [SimpleGroup (Iden (Name "s_name"))],
|
||||
qeHaving = Nothing,
|
||||
qeOrderBy =
|
||||
[SortSpec (Iden (Name "numwait")) Desc NullsOrderDefault,
|
||||
SortSpec (Iden (Name "s_name")) Asc NullsOrderDefault],
|
||||
qeOffset = Nothing, qeFetchFirst = Just (NumLit "100")})
|
||||
|
||||
~~~~
|
||||
|
||||
Output from the simple-sql-parser pretty printer:
|
||||
|
||||
~~~~{.sql}
|
||||
select s_name, count(*) as numwait
|
||||
from supplier,
|
||||
lineitem as l1,
|
||||
orders,
|
||||
nation
|
||||
where s_suppkey = l1.l_suppkey
|
||||
and o_orderkey = l1.l_orderkey
|
||||
and o_orderstatus = 'F'
|
||||
and l1.l_receiptdate > l1.l_commitdate
|
||||
and exists (select *
|
||||
from lineitem as l2
|
||||
where l2.l_orderkey = l1.l_orderkey
|
||||
and l2.l_suppkey <> l1.l_suppkey)
|
||||
and not exists (select *
|
||||
from lineitem as l3
|
||||
where l3.l_orderkey = l1.l_orderkey
|
||||
and l3.l_suppkey <> l1.l_suppkey
|
||||
and l3.l_receiptdate > l3.l_commitdate)
|
||||
and s_nationkey = n_nationkey
|
||||
and n_name = 'INDIA'
|
||||
group by s_name
|
||||
order by numwait desc, s_name
|
||||
fetch first 100 rows only;
|
||||
~~~~
|
||||
|
||||
# Feature support
|
||||
|
||||
* query expressions
|
||||
* * select lists
|
||||
* * from clause
|
||||
* * where clause
|
||||
* * group by clause
|
||||
* * having clause
|
||||
* * order by clause
|
||||
* * offset and fetch
|
||||
* * set operators
|
||||
* * common table expressions
|
||||
* * wide range of value expressions
|
||||
* DDL
|
||||
* * TODO
|
||||
* non-query DML
|
||||
* * TODO
|
||||
* Access control
|
||||
* * TODO
|
||||
* Transaction management
|
||||
* * TODO
|
||||
* Session management
|
||||
* * TODO
|
||||
|
||||
See the [supported_sql.html](supported_sql.html) page for details on
|
||||
the supported SQL.
|
||||
|
||||
Here is a document with all the [simple-sql-parser test
|
||||
cases](test_cases.html) rendered in a webpage so you can get an idea
|
||||
of what it supports.
|
||||
|
||||
# Installation
|
||||
|
||||
Installing the latest release from Hackage.
|
||||
|
||||
~~~~
|
||||
cabal update && cabal install simple-sql-parser
|
||||
~~~~
|
||||
|
||||
Working with the latest development version:
|
||||
|
||||
~~~~
|
||||
git clone https://github.com/JakeWheat/simple-sql-parser.git
|
||||
cd simple-sql-parser
|
||||
cabal sandbox init
|
||||
cabal install --only-dependencies
|
||||
cabal build
|
||||
~~~~
|
||||
|
||||
## Running the tests
|
||||
|
||||
Get the source using 'cabal unpack' or 'git clone', then change to the
|
||||
source directory.
|
||||
|
||||
You can run the tests using cabal:
|
||||
|
||||
~~~~
|
||||
cabal sandbox init
|
||||
cabal install --only-dependencies --enable-tests
|
||||
cabal configure --enable-tests
|
||||
cabal test
|
||||
~~~~
|
||||
|
||||
Or you can run them directly which gives more options. The tests use
|
||||
tasty, which provides the command line options.
|
||||
|
||||
~~~~
|
||||
cabal sandbox init
|
||||
cabal install --only-dependencies --enable-tests
|
||||
cabal configure --enable-tests
|
||||
cabal build
|
||||
dist/build/Tests/Tests
|
||||
~~~~
|
||||
|
||||
--hide-successes is a good option to use:
|
||||
|
||||
~~~~
|
||||
dist/build/Tests/Tests --hide-successes
|
||||
~~~~
|
||||
|
||||
# Documentation
|
||||
|
||||
* see the [simple-sql-parser test cases](test_cases.html) for
|
||||
examples.
|
||||
* [simple-sql-parser haddock](haddock/index.html) (the haddock on
|
||||
Hackage has source links)
|
||||
|
||||
# Recommended reading
|
||||
|
||||
Here is some recommended reading on understanding SQL in depth.
|
||||
\
|
||||
\
|
||||
\
|
||||
SQL: The Complete Reference, 3rd Edition, James R. Groff, Paul
|
||||
N. Weinberg, Andrew J. Oppel
|
||||
|
||||
This is a comprehensive book which covers up to the SQL:1999 standard.
|
||||
\
|
||||
\
|
||||
\
|
||||
SQL in a Nutshell, Kevin Kline, Brand Hunt, Daniel Kline
|
||||
|
||||
This is another good book which covers some of the SQL:2003 and
|
||||
SQL:2008 standards. This means it covers a few newer things like
|
||||
window functions which 'SQL: The Complete Reference' doesn't. It also
|
||||
compares some main SQL product dialects.
|
||||
\
|
||||
\
|
||||
\
|
||||
SQL A Comparative Survey, Hugh Darwen
|
||||
http://bookboon.com/en/sql-a-comparative-survey-ebook
|
||||
|
||||
This is a book about SQL from a relational theory perspective.
|
||||
\
|
||||
\
|
||||
\
|
||||
SQL and Relational Theory, 2nd Edition, Chris Date
|
||||
|
||||
This also covers SQL from a partly theoretical perspective.
|
||||
\
|
||||
\
|
||||
\
|
||||
A Guide to the SQL Standard, C. J. Date, Hugh Darwen
|
||||
|
||||
This is a fantastic book for covering all the little details of the
|
||||
SQL standard in depth. It only covers up to SQL:92.
|
||||
\
|
||||
\
|
||||
\
|
||||
There are several other good books by Chris Date, some with Hugh
|
||||
Darwen and others, for instance 'Introduction to Database Systems',
|
||||
'Temporal Data & the Relational Model, Databases', 'Types and the
|
||||
Relational Model'. Only the first one (Introduction to
|
||||
Database Systems) really relates to SQL.
|
||||
\
|
||||
\
|
||||
\
|
||||
Database Systems: The Complete Book, Hector Garcia-Molina, Jeff Ullman, and Jennifer Widom.
|
||||
|
||||
This book is very comprehensive and has some interesting sections.
|
||||
\
|
||||
\
|
||||
\
|
||||
Some of the SQL draft standards are available to download for free (follow the
|
||||
links on the wikipedia page for SQL). They are a little tricky to
|
||||
read and understand.
|
||||
\
|
||||
\
|
||||
\
|
||||
TODO: add web links for the pdfs below
|
||||
\
|
||||
\
|
||||
\
|
||||
IBM DB2 10.5 SQL Reference Volume 1
|
||||
|
||||
<http://public.dhe.ibm.com/ps/products/db2/info/vr105/pdf/en_US/DB2SQLRefVol1-db2s1e1050.pdf>
|
||||
\
|
||||
\
|
||||
\
|
||||
Oracle SQL Reference 12c release 1
|
||||
|
||||
<http://docs.oracle.com/cd/E16655_01/server.121/e17209.pdf>
|
||||
\
|
||||
\
|
||||
\
|
||||
Teradata:
|
||||
|
||||
TODO
|
||||
\
|
||||
\
|
||||
\
|
||||
Microsoft SQL Server 2012 TSQL reference online. I didn't find a PDF
|
||||
for this.
|
||||
|
||||
<http://technet.microsoft.com/en-us/library/bb510741.aspx>
|
||||
\
|
||||
\
|
||||
\
|
||||
PostgreSQL 9.3 manual:
|
||||
|
||||
<http://www.postgresql.org/docs/9.3/interactive/index.html>
|
||||
|
||||
No PDF for the Postgres manual either, but the web pages are very
|
||||
readable.
|
||||
\
|
||||
\
|
||||
\
|
||||
SQL BNF Grammars
|
||||
|
||||
http://savage.net.au/SQL/index.html
|
||||
|
||||
# Links
|
||||
|
||||
* Homepage: <http://jakewheat.github.io/simple-sql-parser>
|
||||
* Hackage: <http://hackage.haskell.org/package/simple-sql-parser>
|
||||
* Repository: <https://github.com/JakeWheat/simple-sql-parser>
|
||||
* Bug tracker: <https://github.com/JakeWheat/simple-sql-parser/issues>
|
||||
|
||||
# Contact
|
||||
|
||||
jakewheatmail@gmail.com
|
138
website/main.css
Normal file
138
website/main.css
Normal file
|
@ -0,0 +1,138 @@
|
|||
h1, h2 {
|
||||
display:block;
|
||||
background-color: #f0f0f0;
|
||||
border-top: thin #c0c0c0 solid;
|
||||
/*position:relative;*/
|
||||
padding-left:1ex;
|
||||
/*z-index: -10;*/
|
||||
}
|
||||
h1 {
|
||||
font-size: x-large;
|
||||
/*left: -3ex;*/
|
||||
margin-top: 3ex;
|
||||
/*width: 100%;*/
|
||||
}
|
||||
h2 {
|
||||
font-size: large;
|
||||
/*left: -1.5ex;*/
|
||||
margin-top: 1.5ex;
|
||||
/*width: 100%;*/
|
||||
}
|
||||
body {
|
||||
margin-left: 5em;
|
||||
margin-right: 5em;
|
||||
margin-bottom: 5em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
#TOC {
|
||||
float:right;
|
||||
z-index:10;
|
||||
background-color: #f0f0f0;
|
||||
border: thin #c0c0c0 solid;
|
||||
padding:2ex;
|
||||
}
|
||||
.header {
|
||||
/*position:relative;
|
||||
left: -4ex;*/
|
||||
border-top: thin #c0c0c0 solid;
|
||||
border-bottom: thin #c0c0c0 solid;
|
||||
display:inline;
|
||||
padding: 1ex;
|
||||
background-color: #f0f0f0;
|
||||
font-weight: bold;
|
||||
}
|
||||
.footer {
|
||||
text-align: center;
|
||||
font-size: small;
|
||||
}
|
||||
pre {
|
||||
padding: 0.5ex;
|
||||
}
|
||||
|
||||
|
||||
pre {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
/*
|
||||
.SqlPostgresql pre.sourceCode {
|
||||
padding: 0.5em;
|
||||
background-color: #f0f6f6;
|
||||
}
|
||||
.sql pre.sourceCode {
|
||||
padding: 0.5em;
|
||||
background-color: #f0f6f6;
|
||||
}
|
||||
.GeneratedSql .SqlPostgresql pre.sourceCode, .SqlPostgresql .GeneratedSql pre.sourceCode {
|
||||
padding: 0.5em;
|
||||
background-color: #f0f6e0;
|
||||
}
|
||||
.UnusedSql .SqlPostgresql pre.sourceCode, .SqlPostgresql .UnusedSql pre.sourceCode {
|
||||
padding: 0.5em;
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
.haskell,.Haskell pre.sourceCode {
|
||||
background-color: #f5f5d9;
|
||||
}
|
||||
|
||||
.sh pre.sourceCode {
|
||||
padding: 0.5em;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
*/
|
||||
table, tr, td {
|
||||
border-collapse:collapse;
|
||||
cell-padding:2px;
|
||||
cell-spacing:2px;
|
||||
/* padding:2px
|
||||
spacing:2px
|
||||
margin:2px*/
|
||||
vertical-align:top;
|
||||
}
|
||||
td pre {
|
||||
width: 98%;
|
||||
height: 98%;
|
||||
vertical-align:top;
|
||||
}
|
||||
table {
|
||||
width:100%;
|
||||
table-layout:fixed;
|
||||
}
|
||||
td {
|
||||
width: 50%;
|
||||
vertical-align:top;
|
||||
overflow:auto;
|
||||
}
|
||||
hr {
|
||||
border: 0;
|
||||
color: black;
|
||||
background-color: black;
|
||||
height: 1px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
.tablediv {
|
||||
width:100%;
|
||||
}
|
||||
|
||||
/* higlighting kate */
|
||||
|
||||
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre
|
||||
{ /*margin: 2; padding: 2; border: 2; */ vertical-align: baseline; border: none; }
|
||||
td.lineNumbers { border-right: 1px solid #AAAAAA; text-align: right; color: #AAAAAA; padding-right: 5px; padding-left: 5px; }
|
||||
td.sourceCode { padding-left: 5px; }
|
||||
pre.sourceCode { }
|
||||
pre.sourceCode span.Normal { }
|
||||
pre.sourceCode span.Keyword { color: #007020; font-weight: bold; }
|
||||
pre.sourceCode span.DataType { color: #902000; }
|
||||
pre.sourceCode span.DecVal { color: #40a070; }
|
||||
pre.sourceCode span.BaseN { color: #40a070; }
|
||||
pre.sourceCode span.Float { color: #40a070; }
|
||||
pre.sourceCode span.Char { color: #4070a0; }
|
||||
pre.sourceCode span.String { color: #4070a0; }
|
||||
pre.sourceCode span.Comment { color: #60a0b0; font-style: italic; }
|
||||
pre.sourceCode span.Others { color: #007020; }
|
||||
pre.sourceCode span.Alert { color: red; font-weight: bold; }
|
||||
pre.sourceCode span.Function { color: #06287e; }
|
||||
pre.sourceCode span.RegionMarker { }
|
||||
pre.sourceCode span.Error { color: red; font-weight: bold; }
|
26
website/make_website.sh
Executable file
26
website/make_website.sh
Executable file
|
@ -0,0 +1,26 @@
|
|||
#! /bin/sh
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
# todo: check this is run from the project root and not the website/
|
||||
# dir
|
||||
|
||||
mkdir -p build
|
||||
cp website/main.css build
|
||||
cp website/ocean.css build
|
||||
|
||||
# index
|
||||
pandoc --from=markdown --to=html website/index.txt -o build/index.html -c main.css --title=simple-sql-parser --toc
|
||||
pandoc --from=markdown --to=html website/supported_sql.txt -o build/supported_sql.html -c main.css '--title=simple-sql-parser supported SQL' --toc
|
||||
# tpch sql file
|
||||
# pandoc src/tpch.sql -s --highlight-style kate -o tpch.sql.html
|
||||
# rendered test cases
|
||||
runhaskell -package-db=.cabal-sandbox/x86_64-linux-ghc-7.10.2-packages.conf.d -i:tools website/RenderTestCases.lhs > build/test_cases.txt
|
||||
pandoc --from=markdown --to=html build/test_cases.txt -o build/test_cases.html -c main.css '--title=simple-sql-parser examples/test cases' --toc
|
||||
rm build/test_cases.txt
|
||||
# haddock
|
||||
cabal haddock
|
||||
rm -Rf build/haddock
|
||||
mkdir build/haddock/
|
||||
cp -R dist/doc/html/simple-sql-parser/* build/haddock/
|
546
website/ocean.css
Normal file
546
website/ocean.css
Normal file
|
@ -0,0 +1,546 @@
|
|||
/* @group Fundamentals */
|
||||
|
||||
* { margin: 0; padding: 0 }
|
||||
|
||||
/* Is this portable? */
|
||||
html {
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
background: white;
|
||||
color: black;
|
||||
text-align: left;
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0.8em 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin: 0.8em 0 0.8em 2em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0.8em 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
dd {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
a { text-decoration: none; }
|
||||
a[href]:link { color: rgb(196,69,29); }
|
||||
a[href]:visited { color: rgb(171,105,84); }
|
||||
a[href]:hover { text-decoration:underline; }
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Fonts & Sizes */
|
||||
|
||||
/* Basic technique & IE workarounds from YUI 3
|
||||
For reasons, see:
|
||||
http://yui.yahooapis.com/3.1.1/build/cssfonts/fonts.css
|
||||
*/
|
||||
|
||||
body {
|
||||
font:13px/1.4 sans-serif;
|
||||
*font-size:small; /* for IE */
|
||||
*font:x-small; /* for IE in quirks mode */
|
||||
}
|
||||
|
||||
h1 { font-size: 146.5%; /* 19pt */ }
|
||||
h2 { font-size: 131%; /* 17pt */ }
|
||||
h3 { font-size: 116%; /* 15pt */ }
|
||||
h4 { font-size: 100%; /* 13pt */ }
|
||||
h5 { font-size: 100%; /* 13pt */ }
|
||||
|
||||
select, input, button, textarea {
|
||||
font:99% sans-serif;
|
||||
}
|
||||
|
||||
table {
|
||||
font-size:inherit;
|
||||
font:100%;
|
||||
}
|
||||
|
||||
pre, code, kbd, samp, tt, .src {
|
||||
font-family:monospace;
|
||||
*font-size:108%;
|
||||
line-height: 124%;
|
||||
}
|
||||
|
||||
.links, .link {
|
||||
font-size: 85%; /* 11pt */
|
||||
}
|
||||
|
||||
#module-header .caption {
|
||||
font-size: 182%; /* 24pt */
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 85%; /* 11pt */
|
||||
}
|
||||
|
||||
#table-of-contents, #synopsis {
|
||||
/* font-size: 85%; /* 11pt */
|
||||
}
|
||||
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Common */
|
||||
|
||||
.caption, h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: bold;
|
||||
color: rgb(78,98,114);
|
||||
margin: 0.8em 0 0.4em;
|
||||
}
|
||||
|
||||
* + h1, * + h2, * + h3, * + h4, * + h5, * + h6 {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
h1 + h2, h2 + h3, h3 + h4, h4 + h5, h5 + h6 {
|
||||
margin-top: inherit;
|
||||
}
|
||||
|
||||
ul.links {
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
float: right;
|
||||
display: inline-table;
|
||||
margin: 0 0 0 1em;
|
||||
}
|
||||
|
||||
ul.links li {
|
||||
display: inline;
|
||||
border-left: 1px solid #d5d5d5;
|
||||
white-space: nowrap;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.links li a {
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
||||
.hide { display: none; }
|
||||
.show { display: inherit; }
|
||||
.clear { clear: both; }
|
||||
|
||||
.collapser {
|
||||
background-image: url(minus.gif);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.expander {
|
||||
background-image: url(plus.gif);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
p.caption.collapser,
|
||||
p.caption.expander {
|
||||
background-position: 0 0.4em;
|
||||
}
|
||||
.collapser, .expander {
|
||||
padding-left: 14px;
|
||||
margin-left: -14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
pre {
|
||||
padding: 0.25em;
|
||||
margin: 0.8em 0;
|
||||
background: rgb(229,237,244);
|
||||
overflow: auto;
|
||||
border-bottom: 0.25em solid white;
|
||||
/* white border adds some space below the box to compensate
|
||||
for visual extra space that paragraphs have between baseline
|
||||
and the bounding box */
|
||||
}
|
||||
|
||||
.src {
|
||||
background: #f0f0f0;
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
|
||||
.keyword { font-weight: normal; }
|
||||
.def { font-weight: bold; }
|
||||
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Page Structure */
|
||||
|
||||
#content {
|
||||
margin: 0 auto;
|
||||
padding: 0 2em 6em;
|
||||
}
|
||||
|
||||
#package-header {
|
||||
background: rgb(41,56,69);
|
||||
border-top: 5px solid rgb(78,98,114);
|
||||
color: #ddd;
|
||||
padding: 0.2em;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
#package-header .caption {
|
||||
background: url(hslogo-16.png) no-repeat 0em;
|
||||
color: white;
|
||||
margin: 0 2em;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
#package-header a:link, #package-header a:visited { color: white; }
|
||||
#package-header a:hover { background: rgb(78,98,114); }
|
||||
|
||||
#module-header .caption {
|
||||
color: rgb(78,98,114);
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
table.info {
|
||||
float: right;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px solid #ddd;
|
||||
color: rgb(78,98,114);
|
||||
background-color: #fff;
|
||||
max-width: 40%;
|
||||
border-spacing: 0;
|
||||
position: relative;
|
||||
top: -0.5em;
|
||||
margin: 0 0 0 2em;
|
||||
}
|
||||
|
||||
.info th {
|
||||
padding: 0 1em 0 0;
|
||||
}
|
||||
|
||||
div#style-menu-holder {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
#style-menu {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
overflow: visible;
|
||||
background: #374c5e;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
top: 1.25em;
|
||||
}
|
||||
|
||||
#style-menu li {
|
||||
display: list-item;
|
||||
border-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
#style-menu li + li {
|
||||
border-top: 1px solid #919191;
|
||||
}
|
||||
|
||||
#style-menu a {
|
||||
width: 6em;
|
||||
padding: 3px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
#footer {
|
||||
background: #ddd;
|
||||
border-top: 1px solid #aaa;
|
||||
padding: 0.5em 0;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Front Matter */
|
||||
|
||||
#table-of-contents {
|
||||
float: right;
|
||||
clear: right;
|
||||
background: #faf9dc;
|
||||
border: 1px solid #d8d7ad;
|
||||
padding: 0.5em 1em;
|
||||
max-width: 20em;
|
||||
margin: 0.5em 0 1em 1em;
|
||||
}
|
||||
|
||||
#table-of-contents .caption {
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#table-of-contents ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#table-of-contents ul ul {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
#description .caption {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#synopsis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.no-frame #synopsis {
|
||||
display: block;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
height: 80%;
|
||||
top: 10%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#synopsis .caption {
|
||||
float: left;
|
||||
width: 29px;
|
||||
color: rgba(255,255,255,0);
|
||||
height: 110px;
|
||||
margin: 0;
|
||||
font-size: 1px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#synopsis p.caption.collapser {
|
||||
background: url(synopsis.png) no-repeat -64px -8px;
|
||||
}
|
||||
|
||||
#synopsis p.caption.expander {
|
||||
background: url(synopsis.png) no-repeat 0px -8px;
|
||||
}
|
||||
|
||||
#synopsis ul {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#synopsis ul ul {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#synopsis ul,
|
||||
#synopsis ul li.src {
|
||||
background-color: #faf9dc;
|
||||
white-space: nowrap;
|
||||
list-style: none;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Main Content */
|
||||
|
||||
#interface div.top { margin: 2em 0; }
|
||||
#interface h1 + div.top,
|
||||
#interface h2 + div.top,
|
||||
#interface h3 + div.top,
|
||||
#interface h4 + div.top,
|
||||
#interface h5 + div.top {
|
||||
margin-top: 1em;
|
||||
}
|
||||
#interface p.src .link {
|
||||
float: right;
|
||||
color: #919191;
|
||||
border-left: 1px solid #919191;
|
||||
background: #f0f0f0;
|
||||
padding: 0 0.5em 0.2em;
|
||||
margin: 0 -0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
#interface table { border-spacing: 2px; }
|
||||
#interface td {
|
||||
vertical-align: top;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
#interface td.src {
|
||||
white-space: nowrap;
|
||||
}
|
||||
#interface td.doc p {
|
||||
margin: 0;
|
||||
}
|
||||
#interface td.doc p + p {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
.subs dl {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.subs dt {
|
||||
float: left;
|
||||
clear: left;
|
||||
display: block;
|
||||
margin: 1px 0;
|
||||
}
|
||||
|
||||
.subs dd {
|
||||
float: right;
|
||||
width: 90%;
|
||||
display: block;
|
||||
padding-left: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.subs dd.empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.subs dd p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.top p.src {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.subs, .doc {
|
||||
/* use this selector for one level of indent */
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.arguments {
|
||||
margin-top: -0.4em;
|
||||
}
|
||||
.arguments .caption {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fields { padding-left: 1em; }
|
||||
|
||||
.fields .caption { display: none; }
|
||||
|
||||
.fields p { margin: 0 0; }
|
||||
|
||||
/* this seems bulky to me
|
||||
.methods, .constructors {
|
||||
background: #f8f8f8;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
*/
|
||||
|
||||
/* @end */
|
||||
|
||||
/* @group Auxillary Pages */
|
||||
|
||||
#mini {
|
||||
margin: 0 auto;
|
||||
padding: 0 1em 1em;
|
||||
}
|
||||
|
||||
#mini > * {
|
||||
font-size: 93%; /* 12pt */
|
||||
}
|
||||
|
||||
#mini #module-list .caption,
|
||||
#mini #module-header .caption {
|
||||
font-size: 125%; /* 15pt */
|
||||
}
|
||||
|
||||
#mini #interface h1,
|
||||
#mini #interface h2,
|
||||
#mini #interface h3,
|
||||
#mini #interface h4 {
|
||||
font-size: 109%; /* 13pt */
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
|
||||
#mini #interface .top,
|
||||
#mini #interface .src {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#mini #module-list ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#alphabet ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0.5em 0 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#alphabet li {
|
||||
display: inline;
|
||||
margin: 0 0.25em;
|
||||
}
|
||||
|
||||
#alphabet a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#index .caption,
|
||||
#module-list .caption { font-size: 131%; /* 17pt */ }
|
||||
|
||||
#index table {
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
#index .src {
|
||||
font-weight: bold;
|
||||
}
|
||||
#index .alt {
|
||||
font-size: 77%; /* 10pt */
|
||||
font-style: italic;
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
#index td + td {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
#module-list ul {
|
||||
list-style: none;
|
||||
margin: 0 0 0 2em;
|
||||
}
|
||||
|
||||
#module-list li {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
#module-list span.collapser,
|
||||
#module-list span.expander {
|
||||
background-position: 0 0.3em;
|
||||
}
|
||||
|
||||
#module-list .package {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* @end */
|
161
website/supported_sql.txt
Normal file
161
website/supported_sql.txt
Normal file
|
@ -0,0 +1,161 @@
|
|||
# simple-sql-parser supported SQL overview
|
||||
|
||||
[simple-sql-parser home](index.html)
|
||||
|
||||
This page has more details on the supported SQL in simple-sql-parser.
|
||||
|
||||
See the [simple-sql-parser test cases](test_cases.html) page for
|
||||
examples.
|
||||
|
||||
The target dialect of SQL at this time is ISO/ANSI SQL:2011. The
|
||||
parser supports queries, DDL, non-query DML, access control, transaction
|
||||
management and session management syntax. The parser and syntax does
|
||||
not follow the standard grammar closely - they permit a lot of things
|
||||
which the grammar in the standard forbids. The intended usage is that
|
||||
an additional pass over the ast can be made if you want to carefully
|
||||
prohibit everything that the standard doesn't allow.
|
||||
|
||||
Apart from this permissiveness, some work has been put into trying to
|
||||
get the best parser error messages possible.
|
||||
|
||||
Although the parser and syntax support some character set constructs,
|
||||
any source is always parsed in the default system encoding which
|
||||
Haskell uses, and any encoding/decoding is left to the system. I think
|
||||
this effectively means that you will usually be using utf-8 character
|
||||
set for the sql source.
|
||||
|
||||
# Queries
|
||||
|
||||
## Select lists
|
||||
|
||||
Supports value expressions, aliases with optional 'as'.
|
||||
|
||||
Doesn't support 'select * as (a,b,c) from t' yet.
|
||||
|
||||
## Set quantifiers on select
|
||||
|
||||
Supports 'select distinct' and explicit 'select all'.
|
||||
|
||||
## From clause
|
||||
|
||||
* aliases
|
||||
* subqueries
|
||||
* functions
|
||||
* joins
|
||||
- natural
|
||||
- inner
|
||||
- left/right/full outer
|
||||
- cross
|
||||
- on expressions
|
||||
- using lists
|
||||
- lateral
|
||||
|
||||
## Group by clause
|
||||
|
||||
Supports value expressions, group by (), cube, rollup, grouping
|
||||
parentheses and grouping sets with nested grouping expressions.
|
||||
|
||||
## Order by clause
|
||||
|
||||
Supports value expressions, asc/desc and nulls first/last.
|
||||
|
||||
## Offset and fetch
|
||||
|
||||
Supports 'offset n rows' and 'fetch first n rows only'.
|
||||
|
||||
## Set operators
|
||||
|
||||
Union, except, intersect + all/distinct and corresponding.
|
||||
|
||||
## Table value constructor
|
||||
|
||||
For example: values (1,2),(3,4).
|
||||
|
||||
## Explicit table
|
||||
|
||||
For example: 'table t', which is shorthand for 'select * from t'.
|
||||
|
||||
## Value expressions
|
||||
|
||||
The value expressions type and parser is used in many contexts,
|
||||
including:
|
||||
|
||||
* select lists;
|
||||
* where clause expressions;
|
||||
* group by clause expressions;
|
||||
* having clause expressions;
|
||||
* order by clause expressions;
|
||||
* offset and fetch clause expressions;
|
||||
* table value constructors.
|
||||
|
||||
This doesn't exactly follow the ANSI Standards, which have separate
|
||||
grammars for most of these.
|
||||
|
||||
The supported value expressions include:
|
||||
|
||||
* basic string literals in single quotes (escapes and other string
|
||||
literal syntaxes coming soon)
|
||||
* number literals: digits.digitse+-exp
|
||||
* explicitly typed literal, e.g. int '3'
|
||||
* binary operators
|
||||
- comparisons: = != <> <= >= < >
|
||||
- arithmetic: + - / * % ^
|
||||
- logic: and, or
|
||||
- bitwise: & | (and ^ as above)
|
||||
- string: ||, like, not like
|
||||
- other: overlaps, is similar to, is not similar too, is distinct
|
||||
from, is not distinct from
|
||||
* prefix unary operators
|
||||
- +, -
|
||||
- not
|
||||
- ~
|
||||
* postfix unary
|
||||
- is null, is not null
|
||||
- is true, is not true, is false, is not false, is unknown, is not unknown
|
||||
* other operators
|
||||
- extract (extract(day from dt))
|
||||
- position (position string1 in string2)
|
||||
- substring (substring(x from 2 for 4))
|
||||
- convert (convert(string using conversion))
|
||||
- translate (translate(string using translation))
|
||||
- overlay (overlay (string placing embedded_string from start for
|
||||
length))
|
||||
- trim (trim(leading '_' from s))
|
||||
- between (a between 1 and 5)
|
||||
- in list (a in (1,2,3,4))
|
||||
- cast (cast(a as int))
|
||||
* subqueries
|
||||
- in subquery
|
||||
- any/some/all
|
||||
- exists
|
||||
* case expressions
|
||||
* parentheses
|
||||
* quoted and unquoted identifiers
|
||||
* a.b qualified identifiers
|
||||
* \*, a.\*
|
||||
* functions: f(a,b)
|
||||
* aggregates: agg(distinct a order by b)
|
||||
* window functions: sum(x) over (partition by y order by z)
|
||||
plus some explicit frame support (same as in postgres 9.3)
|
||||
* row constructors, e.g. where (a,b) = any (select a,b from t)
|
||||
* ? used in parameterized queries
|
||||
|
||||
# DDL
|
||||
|
||||
todo
|
||||
|
||||
# Non-query DML
|
||||
|
||||
todo
|
||||
|
||||
# Access Control
|
||||
|
||||
todo
|
||||
|
||||
# Transaction management
|
||||
|
||||
todo
|
||||
|
||||
# Session management
|
||||
|
||||
todo
|
Loading…
Reference in a new issue