1
Fork 0

restrict parsing of * and X.* as term in expressions

This commit is contained in:
Jake Wheat 2024-02-08 10:43:11 +00:00
parent 6e1e377308
commit 742382fcc0
7 changed files with 127 additions and 135 deletions
Language/SQL/SimpleSQL

View file

@ -604,12 +604,19 @@ simpleLiteral = numberLit <|> stringLit
=== star
used in select *, select x.*, and agg(*) variations, and some other
places as well. The parser doesn't attempt to check that the star is
in a valid context, it parses it OK in any scalar expression context.
places as well. The parser makes an attempt to not parse star in
most contexts, to provide better experience when the user makes a mistake
in an expression containing * meaning multiple. It will parse a *
at the top level of a select item, or in arg in a app argument list.
-}
star :: Parser ScalarExpr
star = Star <$ symbol "*"
star =
hidden $ choice
[Star <$ symbol "*"
-- much easier to use try here than to left factor where
-- this is allowed and not allowed
,try (QStar <$> (names <* symbol "." <* symbol "*"))]
{-
== parameter
@ -957,12 +964,12 @@ app :: Parser ([Name] -> ScalarExpr)
app =
hidden openParen *> choice
[hidden duplicates
<**> (commaSep1 scalarExpr
<**> (commaSep1 scalarExprOrStar
<**> ((hoption [] orderBy <* closeParen)
<**> (hoptional afilter <$$$$$> AggregateApp)))
-- separate cases with no all or distinct which must have at
-- least one scalar expr
,commaSep1 scalarExpr
,commaSep1 scalarExprOrStar
<**> choice
[closeParen *> hidden (choice
[window
@ -1310,13 +1317,19 @@ documenting/fixing.
scalarExpr :: Parser ScalarExpr
scalarExpr = label "expression" $ E.makeExprParser term (opTable False)
-- used when parsing contexts where a * or x.* is allowed
-- currently at the top level of a select item or top level of
-- argument passed to an app-like. This list may need to be extended.
scalarExprOrStar :: Parser ScalarExpr
scalarExprOrStar = label "expression" (star <|> scalarExpr)
term :: Parser ScalarExpr
term = label "expression" $
choice
[simpleLiteral
,parameter
,positionalArg
,star
,parensExpr
,caseExpr
,cast
@ -1383,8 +1396,12 @@ duplicates =
-}
selectItem :: Parser (ScalarExpr,Maybe Name)
selectItem = label "select item" ((,) <$> scalarExpr <*> optional als)
where als = label "alias" $ optional (keyword_ "as") *> name
selectItem =
label "select item" $ choice
[(,Nothing) <$> star
,(,) <$> scalarExpr <*> optional als]
where
als = label "alias" $ optional (keyword_ "as") *> name
selectList :: Parser [(ScalarExpr,Maybe Name)]
selectList = commaSep1 selectItem

View file

@ -87,6 +87,7 @@ scalarExpr _ (IntervalLit s v f t) =
<+> me (\x -> pretty "to" <+> intervalTypeField x) t
scalarExpr _ (Iden i) = names i
scalarExpr _ Star = pretty "*"
scalarExpr _ (QStar nms) = names nms <> pretty ".*"
scalarExpr _ Parameter = pretty "?"
scalarExpr _ (PositionalArg n) = pretty $ T.cons '$' $ showText n
scalarExpr _ (HostParameter p i) =

View file

@ -105,8 +105,10 @@ data ScalarExpr
-- | identifier with parts separated by dots
| Iden [Name]
-- | star, as in select *, t.*, count(*)
-- | star, as in select *, count(*)
| Star
-- | qualified star, as in a.*, b.c.*
| QStar [Name]
| Parameter -- ^ Represents a ? in a parameterized query
| PositionalArg Int -- ^ Represents an e.g. $1 in a parameterized query