jakewheat / hssqlppp Goto Github PK
View Code? Open in Web Editor NEWSQL parser and type checker in Haskell
Home Page: http://jakewheat.github.com/hssqlppp/latest
License: BSD 3-Clause "New" or "Revised" License
SQL parser and type checker in Haskell
Home Page: http://jakewheat.github.com/hssqlppp/latest
License: BSD 3-Clause "New" or "Revised" License
PostgreSQL (and, I think, many other RDBMs) requires table identifiers to be quoted in many cases. But HsSqlPpp does not quote them.
For example, printStatement generates:
select ... from Record r, Submmission s ...
while we need:
select ... from "Record" r, "Submission" s ...
Seems such a quoting might be done with simple patch. In Pretty.lhs replace convDqi definition with following:
convDqi :: SQIdentifier -> Doc
convDqi (SQIdentifier _ is) = hcat $ punctuate (text ".") $ map (text . quot) is
where quot x = """ ++ x ++ """
Currently, the default value of a table attribute is treated specially (compared to other column constraints). It is stored in the def
field of AttributeDef
and parsed separately. I understand that this design facilitates type checking, but it prevents the processing of several valid attribute definitions.
According to the grammar for CREATE TABLE in the PostgreSQL documentation, the DEFAULT
keyword introduces a constraint like any other. This means we can place it after other constraints:
CREATE TABLE t (a integer NOT NULL DEFAULT 1);
We can also name it explicitly:
CREATE TABLE t (a integer CONSTRAINT adefault DEFAULT 1);
Both these definitions are accepted by PostgreSQL (and the former is accepted by many other database systems), but rejected by the hssqlppp parser.
I would like to use hssqlppp to parse some existing table definitions, which unfortunately contain constraints in many different orders. For my application, it is important that pretty-printing a parsed definition does not significantly alter the SQL. I therefore recommend treating DEFAULT
just like the other column constraints (i.e. adding a DefaultConstraint
constructor to RowConstraint
, parsing it inside the choice
, etc.). This allows me to output something very similar to what I've read, and I think it might be reasonably easy to implement. It does mean the default value will have to be retrieved using listToMaybe [v | DefaultConstraint _ _ v <- constraints]
.
In version 0.4, one could construct a Catalog
with emptyCatalog
or defaultCatalog
, and a list of catalog updates. In 0.6, emptyCatalog
/defaultCatalog
seem to be gone, so it's unclear how to construct a catalog.
Type expressions with multiple arguments like
NUMERIC(9,2)
are not recognized.
HsSqlPpp version: latest as of 16 Dec, 2010.
This is with GHC-7.0.3 and hssqlppp-0.4.0
> parseStatements "" "SELECT * FROM mytable WHERE column = 3;"
Left (line 1, column 29):
unexpected IdStringTok "column"
expecting operator
:1:29:
Context:
SELECT * FROM mytable WHERE column = 3;
^
ERROR HERE
There is a bunch of errors like this:
Ambiguous occurrence ‘<>’
It could refer to either ‘Prelude.<>’,
imported from ‘Prelude’ at /Users/int-index/Projects/hssqlppp/hssqlppp/src/Database/HsSqlPpp/Internals/PrettyInternal.lhs:8:10-51
(and originally defined in ‘GHC.Base’)
or ‘Text.PrettyPrint.<>’,
imported from ‘Text.PrettyPrint’ at /Users/int-index/Projects/hssqlppp/hssqlppp/src/Database/HsSqlPpp/Internals/PrettyInternal.lhs:19:3-25
(and originally defined in ‘Text.PrettyPrint.HughesPJ’)
|
483 | > label lb <>
|
Fixed by adding this line in Database.HsSqlPpp.Internals.PrettyInternal
:
> import Prelude hiding ((<>))
The following expression is parsed
CAST(1 AS INT)
but
1::INT
is NG.
HsSqlPpp version: latest as of 16 Dec, 2010.
Is it possible to add parsing of regexp in SQL-query? For example: ... CASE WHEN layer~E'^-?\\d+$' ...
In version 0.4, there were predefined types (typeBool
etc.), which now seem to gone. Is there any reason for this?
The "WHERE" introducing a WHERE clause cannot be upper case. I cannot see any obvious reason in ParserInternal.lhs
for a distinction between "where" and "WHERE", but I guess it's something to do with keyword
. "Where", "wherE" and "wHeRe" etc. all fail.
import Database.HsSqlPpp.Parser
import Database.HsSqlPpp.Pretty
uppercase = parseQueryExpr "filename" "SELECT * FROM table1 WHERE true"
uppercaseParens = parseQueryExpr "filename" "SELECT * FROM table1 WHERE (true)"
lowercase = parseQueryExpr "filename" "SELECT * FROM table1 where true"
uppercase
fails to parse
*Main> uppercase
Left "filename" (line 1, column 28):
unexpected ("filename" (line 1, column 28),IdStringTok "true")
expecting operator or end of input
filename:1:28:
Context:
SELECT * FROM table1 WHERE true
^
ERROR HERE
uppercaseParens
parses to the wrong thing. It thinks "WHERE" is part of a FullAlias
.
*Main> uppercaseParens
... (FullAlias (Annotation {asrc = Just ("filename",1,22), atype = Nothing, errs = [], stType = Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) (Nmc "WHERE") [Nmc "true"])]
lowercase
works fine
I applied parseStatements defaultParseFlags "" Nothing
to pg_dump
output and got this parse error:
(line 31, column 29):
unexpected Identifier Nothing "ENUM"
:31:29:
Context:
--
-- Name: privilege; Type: TYPE; Schema: v1; Owner: int-index
--
CREATE TYPE v1.privilege AS ENUM (
^
ERROR HERE
'orphan',
'disabled',
'poor'
);
I suppose it contains enough context.
There is a broken link in /Internals/AstInternal.ag to devel.txt.html, see #14
Trying to build with the Stack lts-8.16 release fails with the following error:
hssqlppp-0.6.1: build (lib + test)
Log files have been written to: /home/ayo/hs/hssqlppp/.stack-work/logs/
Progress: 1/4
-- While building package hssqlppp-0.6.1 using:
/home/ayo/.stack/setup-exe-cache/x86_64-linux/Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 --builddir=.stack-work/dist/x86_64-linux/Cabal-1.24.2.0 build lib:hssqlppp test:Tests --ghc-options " -ddump-hi -ddump-to-file"
Process exited with code: ExitFailure 1
Logs have been written to: /home/ayo/hs/hssqlppp/.stack-work/logs/hssqlppp-0.6.1.log
Configuring hssqlppp-0.6.1...
Preprocessing library hssqlppp-0.6.1...
Preprocessing test suite 'Tests' for hssqlppp-0.6.1...
[ 1 of 84] Compiling Database.HsSqlPpp.Utils.Here ( tests/Database/HsSqlPpp/Utils/Here.lhs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Tests/Tests-tmp/Database/HsSqlPpp/Utils/Here.o )
[ 2 of 84] Compiling Database.HsSqlPpp.Utils.GroomUtils ( tests/Database/HsSqlPpp/Utils/GroomUtils.lhs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Tests/Tests-tmp/Database/HsSqlPpp/Utils/GroomUtils.o )
/home/ayo/hs/hssqlppp/hssqlppp/tests/Database/HsSqlPpp/Utils/GroomUtils.lhs:22:24: error:
• Expecting one more argument to ‘Exp’
Expected a type, but ‘Exp’ has kind ‘* -> *’
• In the type signature:
groomF :: Show a => (Exp -> Exp) -> a -> String
/home/ayo/hs/hssqlppp/hssqlppp/tests/Database/HsSqlPpp/Utils/GroomUtils.lhs:22:31: error:
• Expecting one more argument to ‘Exp’
Expected a type, but ‘Exp’ has kind ‘* -> *’
• In the type signature:
groomF :: Show a => (Exp -> Exp) -> a -> String
make: *** [Makefile:40: test] Error 1
This seems like a really interesting library, especially the type-checking part. Would it be possible to answer the following questions:
E.g.,
> parseQueryExpr defaultParseFlags "" Nothing "select 'a' :: text"
Left (line 1, column 12):
unexpected (("",1,12),Symbol ":")
expecting operator or end of input
cannot make functioncall from StringLit (Annotation {anSrc = Just ("",1,8), anType = Nothing, anErrs = [], anImplicitCast = Nothing, anCatUpd = []}) "a"
:1:12:
Context:
select 'a' :: text
^
ERROR HERE
I want to retrieve the list of types of Placeholder
s in a typechecked Statement
. This would be significantly easier with a Generic
instance for most datatypes.
I'm happy to send a PR with instances, though looking at the ag
files has me a little confused: I'd have thought it to be just a question of adding deriving <Type>: <classes>
, but it seems as though ScalarExpr
has more instances than I can find in the source file.
The latest version of this package on Hackage is now incompatible with the modern version of "mtl". However as I've seen in this repository, the issue has already been fixed a couple of months ago. Please upload the changes to Hackage.
Example ghci runs:
Prelude Database.HsSqlPpp.Parse Database.HsSqlPpp.Dialect> parseStatements (ParseFlags postgresDialect) "something" Nothing "select ~2 from pg_stat_activity;"
Left "asdas" (line 1, column 8):
unexpected Symbol "~"
expecting expression
asdas:1:8:
Context:
select ~2 from pg_stat_activity;
^
ERROR HERE
Prelude Database.HsSqlPpp.Parse Database.HsSqlPpp.Dialect> parseStatements (ParseFlags postgresDialect) "something" Nothing "select 2 << 3 from pg_stat_activity;"
Left "asdas" (line 1, column 10):
unexpected Symbol "<<"
expecting operator
cannot make functioncall from NumberLit (Annotation {anSrc = Just ("asdas",1,8), anType = Nothing, anErrs = [], anImplicitCast = Nothing, anCatUpd = []}) "2"
asdas:1:10:
Context:
select 2 << 3 from pg_stat_activity;
^
ERROR HERE
Prelude Database.HsSqlPpp.Parse Database.HsSqlPpp.Dialect> parseStatements (ParseFlags postgresDialect) "something" Nothing "select 2 >> 3 from pg_stat_activity;"
Left "asdas" (line 1, column 10):
unexpected Symbol ">>"
expecting operator
cannot make functioncall from NumberLit (Annotation {anSrc = Just ("asdas",1,8), anType = Nothing, anErrs = [], anImplicitCast = Nothing, anCatUpd = []}) "2"
asdas:1:10:
Context:
select 2 >> 3 from pg_stat_activity;
^
ERROR HERE
Prelude Database.HsSqlPpp.Parse Database.HsSqlPpp.Dialect> parseStatements (ParseFlags postgresDialect) "something" Nothing "select 2 # 1 from pg_stat_activity;"
Left "asdas" (line 1, column 10):
unexpected Symbol "#"
expecting operator
cannot make functioncall from NumberLit (Annotation {anSrc = Just ("asdas",1,8), anType = Nothing, anErrs = [], anImplicitCast = Nothing, anCatUpd = []}) "2"
asdas:1:10:
Context:
select 2 # 1 from pg_stat_activity;
^
ERROR HERE
All of the above are valid postgres operators according to the manual at http://www.postgresql.org/docs/current/static/functions-math.html and statements themselves run fine in the postgres cli.
As far as I see, HsSqlPpp parser (and AST?) does not support COUNT(DISTINCT column_name) syntax at all. For example,
> parseQueryExpr "" "SELECT COUNT(DISTINCT column) FROM table"
Right (Select (Annotation {asrc = Just ("",1,1), atype = Nothing, errs = [],
stType = Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) Dupes
(SelectList (Annotation {asrc = Just ("",1,8), atype = Nothing, errs = [],
stType = Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) [SelExp
(Annotation {asrc = Just ("",1,8), atype = Nothing, errs = [], stType =
Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) (FunCall
(Annotation {asrc = Just ("",1,13), atype = Nothing, errs = [], stType =
Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) "count"
[Identifier (Annotation {asrc = Just ("",1,23), atype = Nothing, errs = [],
stType = Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) "column"])])
[Tref (Annotation {asrc = Just ("",1,31), atype = Nothing, errs = [], stType =
Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) (SQIdentifier
(Annotation {asrc = Just ("",1,31), atype = Nothing, errs = [], stType =
Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}) ["table"])
(NoAlias (Annotation {asrc = Just ("",1,31), atype = Nothing, errs = [],
stType = Nothing, catUpd = [], fnProt = Nothing, infType = Nothing}))] Nothing
[] Nothing [] Nothing Nothing)
The simplest (but hacky) way to fix this seems to add dummy Boolean argument to COUNT function in the AST. For example, COUNT(False, field) will mean COUNT(field) and COUNT(True, field) will mean COUNT(DISTINCT field). But maybe we need more generic support for such cases in AST?
Please make a release of the 0.5 version of the library on Hackage/Stackage. 0.5 has a lot of improvements over 0.4 and seems pretty stable. I've been using it in my production code through stack git URL support for months now. But it'll be nice to pull it from H(St)ackage directly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.