packages feed

postgresql-syntax 0.4.1.3 → 0.4.2

raw patch · 4 files changed

+68/−3 lines, 4 files

Files

library/PostgresqlSyntax/Extras/HeadedMegaparsec.hs view
@@ -20,7 +20,19 @@ -- * Executors  run :: (Ord err, VisualStream strm, TraversableStream strm, Megaparsec.ShowErrorComponent err) => HeadedParsec err strm a -> strm -> Either String a-run p = first Megaparsec.errorBundlePretty . Megaparsec.runParser (toParsec p <* Megaparsec.eof) ""+run p = first Megaparsec.errorBundlePretty . runParser p++-- |+-- Run the parser but returns all the error messages separated, along with their offset in the parsed message.+runParserWithErrorPos :: (Show (Megaparsec.Token strm), Show e, Ord e, VisualStream strm, TraversableStream strm, Megaparsec.ShowErrorComponent e) => HeadedParsec e strm a -> strm -> Either (NonEmpty (Int, String)) a+runParserWithErrorPos p s = case runParser p s of+  Left err -> Left (extractor <$> Megaparsec.bundleErrors err)+  Right v -> Right v+  where+    extractor x = (Megaparsec.errorOffset x, Megaparsec.parseErrorPretty x)++runParser :: (Ord e, VisualStream strm, TraversableStream strm) => HeadedParsec e strm a -> strm -> Either (Megaparsec.ParseErrorBundle strm e) a+runParser p = Megaparsec.runParser (toParsec p <* Megaparsec.eof) ""  -- * Primitives 
library/PostgresqlSyntax/Parsing.hs view
@@ -54,6 +54,9 @@ run :: Parser a -> Text -> Either String a run = Extras.run +runWithPosError :: Parser a -> Text -> Either (NonEmpty (Int, String)) a+runWithPosError = Extras.runParserWithErrorPos+ -- * Helpers  commaSeparator :: Parser ()@@ -115,6 +118,23 @@          in collectChunks mempty   return tail +-- |+-- >>> testParser dollarQuotedSconst "$$it's good$$"+-- "it's good"+dollarQuotedSconst :: Parser Text+dollarQuotedSconst = do+  char '$'+  quoteTag <- takeWhileP Nothing (/= '$')+  let terminator = Megaparsec.chunk $ "$" <> quoteTag <> "$"+  char '$'+  endHead+  tail <-+    parse $ do+      body <- many $ Megaparsec.notFollowedBy terminator *> Megaparsec.anySingle+      terminator+      return $ Text.pack body+  return tail+ atEnd :: Parser a -> Parser a atEnd p = space *> p <* endHead <* space <* eof @@ -1552,7 +1572,7 @@  fconst = float -sconst = quotedString '\''+sconst = quotedString '\'' <|> dollarQuotedSconst  constTypename =   asum
postgresql-syntax.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: postgresql-syntax-version: 0.4.1.3+version: 0.4.2 category: Database, PostgreSQL, Parsing synopsis: PostgreSQL AST parsing and rendering description:
tasty-test/Main.hs view
@@ -1,5 +1,6 @@ module Main where +import qualified Data.List.NonEmpty as NonEmpty import qualified Data.Text as Text import qualified PostgresqlSyntax.Parsing as Parsing import Test.Tasty@@ -56,6 +57,38 @@                       "inet",                       "json",                       "jsonb"+                    ],+                  testParserOnAllInputs+                    "sconst"+                    Parsing.sconst+                    [ "'it''s good'",+                      "$$it's good$$",+                      "$x$it's good$x$"                     ]+                ],+        testGroup "Error reporting"+          $ let testParserOnAllInputs parserName parser inputs res =+                  testCase parserName+                    $ forM_ inputs+                    $ \input -> case Parsing.runWithPosError parser input of+                      Left err -> show (NonEmpty.head err) @?= res+                      Right _ -> return ()+             in [ testParserOnAllInputs+                    "Typo in FROM keyword"+                    Parsing.preparableStmt+                    [ "select i :: int8 fom auth.user as u\n\+                      \inner join edgenode.usere_provider as p\n\+                      \on u.id = p.user_id\n\+                      \inner join edgenode.provider_branch as b\n\+                      \on b.provider_fk = p.provider_id"+                    ]+                    "(20,\"offset=20:\\nunexpected space\\nexpecting end of input\\n\")",+                  testParserOnAllInputs+                    "Typo in NOT keyword"+                    Parsing.preparableStmt+                    [ "select i :: int8 from auth.user as u\n\+                      \WHERE u.id IS NO NULL && TRUE"+                    ]+                    "(53,\"offset=53:\\nexpecting white space\\n\")"                 ]       ]