From f0668233d69854d215cf3204925b4d5e3c66ecf0 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 20:50:08 +0100 Subject: [PATCH 1/8] Accept any path for table relations --- src/SqlSquared/Parser.purs | 2 +- src/SqlSquared/Path.purs | 14 +++++++++++++- src/SqlSquared/Signature/Relation.purs | 8 +++++--- test/src/Constructors.purs | 4 ++-- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/SqlSquared/Parser.purs b/src/SqlSquared/Parser.purs index f2ef7cb..38c73e1 100644 --- a/src/SqlSquared/Parser.purs +++ b/src/SqlSquared/Parser.purs @@ -570,7 +570,7 @@ parenRelation = do tableRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) tableRelation = do i ← ident - path ← Pt.parseAnyFilePath P.fail i + path ← Pt.parseAnyPath P.fail i a ← PC.optionMaybe do _ ← keyword "as" ident diff --git a/src/SqlSquared/Path.purs b/src/SqlSquared/Path.purs index 294afe0..4ac9a94 100644 --- a/src/SqlSquared/Path.purs +++ b/src/SqlSquared/Path.purs @@ -3,6 +3,8 @@ module SqlSquared.Path , printAnyFilePath , parseAnyDirPath , printAnyDirPath + , parseAnyPath + , printAnyPath , genAnyFilePath , genAnyDirPath , module PathyTypeReexprts @@ -20,7 +22,6 @@ import Pathy (AnyDir, AnyFile) import Pathy.Gen as PtGen import SqlSquared.Utils ((∘)) - printAnyDirPath :: AnyDir -> String printAnyDirPath = E.either (Pt.sandboxAny >>> Pt.unsafePrintPath Pt.posixPrinter) @@ -47,6 +48,17 @@ parseAnyFilePath fail = Pt.parsePath Pt.posixParser (pure ∘ E.Left) (fail "Expected valid path") +printAnyPath :: E.Either AnyDir AnyFile -> String +printAnyPath = E.either printAnyDirPath printAnyFilePath + +parseAnyPath :: forall m. Applicative m => (forall a. String -> m a) -> String -> m (E.Either AnyDir AnyFile) +parseAnyPath fail = Pt.parsePath Pt.posixParser + (pure ∘ E.Left ∘ E.Right) + (pure ∘ E.Left ∘ E.Left) + (pure ∘ E.Right ∘ E.Right) + (pure ∘ E.Right ∘ E.Left) + (fail "Expected valid path") + genAnyFilePath :: forall m. Gen.MonadGen m => MonadRec m => m AnyFile genAnyFilePath = Gen.oneOf $ (E.Left <$> PtGen.genAbsFilePath) diff --git a/src/SqlSquared/Signature/Relation.purs b/src/SqlSquared/Signature/Relation.purs index 98f030f..eb3fabb 100644 --- a/src/SqlSquared/Signature/Relation.purs +++ b/src/SqlSquared/Signature/Relation.purs @@ -5,6 +5,7 @@ import Prelude import Control.Monad.Gen as Gen import Control.Monad.Gen.Common as GenC import Control.Monad.Rec.Class (class MonadRec) +import Data.Either (Either(..), either) import Data.Foldable as F import Data.Maybe (Maybe) import Data.NonEmpty ((:|)) @@ -15,6 +16,7 @@ import SqlSquared.Path as Pt import SqlSquared.Signature.Ident as ID import SqlSquared.Signature.JoinType as JT import SqlSquared.Utils ((∘)) + type JoinRelR a = { left ∷ Relation a , right ∷ Relation a @@ -33,7 +35,7 @@ type VariRelR = } type TableRelR = - { path ∷ Pt.AnyFile + { path ∷ Either Pt.AnyDir Pt.AnyFile , alias ∷ Maybe String } @@ -86,7 +88,7 @@ printRelation = case _ of ":" <> ID.printIdent vari <> F.foldMap (\a → " AS " <> ID.printIdent a) alias TableRelation { path, alias } → "`" - <> Pt.printAnyFilePath path + <> either Pt.printAnyDirPath Pt.printAnyFilePath path <> "`" <> F.foldMap (\x → " AS " <> ID.printIdent x) alias JoinRelation { left, right, joinType, clause } → @@ -117,7 +119,7 @@ genRelation n = alias ← GenC.genMaybe GenS.genUnicodeString pure $ VariRelation { vari, alias } genTable = do - path ← Pt.genAnyFilePath + path ← Right <$> Pt.genAnyFilePath alias ← GenC.genMaybe GenS.genUnicodeString pure $ TableRelation { path, alias } genExpr = do diff --git a/test/src/Constructors.purs b/test/src/Constructors.purs index 873a83e..9efdc94 100644 --- a/test/src/Constructors.purs +++ b/test/src/Constructors.purs @@ -23,7 +23,7 @@ selectQuery = ] ( Just $ S.TableRelation { alias: Nothing - , path: E.Left + , path: E.Right $ E.Left $ Pt.rootDir Pt. Pt.dir (SProxy :: SProxy "mongo") Pt. Pt.dir (SProxy :: SProxy "testDb") @@ -50,7 +50,7 @@ buildSelectQuery = ∘ (S._relations ?~ (S.TableRelation { alias: Nothing - , path: E.Left + , path: E.Right $ E.Left $ Pt.rootDir Pt. Pt.dir (SProxy :: SProxy "mongo") Pt. Pt.dir (SProxy :: SProxy "testDb") From 5b721008369586cb74457ee7e53623ec8e4a5f24 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 22:56:09 +0100 Subject: [PATCH 2/8] Rename pars to parens for consistency --- src/SqlSquared.purs | 2 +- src/SqlSquared/Constructors.purs | 4 ++-- src/SqlSquared/Parser.purs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/SqlSquared.purs b/src/SqlSquared.purs index 5deec52..6e02637 100644 --- a/src/SqlSquared.purs +++ b/src/SqlSquared.purs @@ -22,7 +22,7 @@ import Data.Functor.Mu (Mu) import Data.Json.Extended as EJ import Data.Traversable (traverse) import Matryoshka (cata, anaM) -import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, pars, projection, select, set, splice, string, switch, then_, unop, vari, when) as Constructors +import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, parens, projection, select, set, splice, string, switch, then_, unop, vari, when) as Constructors import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Ident, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Vari, _VariRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses import SqlSquared.Parser (Literal(..), PositionedToken, Token(..), TokenStream, parse, parseModule, parseQuery, prettyParse, printToken, tokenize) as Parser import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VariRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig diff --git a/src/SqlSquared/Constructors.purs b/src/SqlSquared/Constructors.purs index a54e7b7..4aceef4 100644 --- a/src/SqlSquared/Constructors.purs +++ b/src/SqlSquared/Constructors.purs @@ -124,5 +124,5 @@ buildSelect f = , orderBy: Nothing } -pars ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ t → t -pars = embed ∘ Sig.Parens +parens ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ t → t +parens = embed ∘ Sig.Parens diff --git a/src/SqlSquared/Parser.purs b/src/SqlSquared/Parser.purs index 38c73e1..907fe57 100644 --- a/src/SqlSquared/Parser.purs +++ b/src/SqlSquared/Parser.purs @@ -691,7 +691,7 @@ _LIKE ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ Maybe t → t → t → _LIKE mbEsc lhs rhs = C.invokeFunction "LIKE" $ lhs : rhs : (fromMaybe (C.string "\\") mbEsc) : L.Nil _NOT ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ t → t -_NOT = C.unop Sig.Not ∘ C.pars +_NOT = C.unop Sig.Not ∘ C.parens _BINOP ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ t → Sig.BinaryOperator → t → t _BINOP = flip C.binop From 3b26f417ea88d71ddd2c15c2a395b692e23b4e0b Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 23:45:25 +0100 Subject: [PATCH 3/8] Use a type for identifiers rather than naked strings --- src/SqlSquared.purs | 6 ++-- src/SqlSquared/Constructors.purs | 16 ++++++---- src/SqlSquared/Lenses.purs | 14 ++++----- src/SqlSquared/Parser.purs | 27 +++++++++-------- src/SqlSquared/Signature.purs | 36 +++++++++++----------- src/SqlSquared/Signature/Ident.purs | 38 ++++++++++++++++-------- src/SqlSquared/Signature/Projection.purs | 6 ++-- src/SqlSquared/Signature/Relation.purs | 28 ++++++++--------- test/src/Argonaut.purs | 2 +- test/src/Gen.purs | 5 ++-- 10 files changed, 99 insertions(+), 79 deletions(-) diff --git a/src/SqlSquared.purs b/src/SqlSquared.purs index 6e02637..04e9b28 100644 --- a/src/SqlSquared.purs +++ b/src/SqlSquared.purs @@ -23,9 +23,9 @@ import Data.Json.Extended as EJ import Data.Traversable (traverse) import Matryoshka (cata, anaM) import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, parens, projection, select, set, splice, string, switch, then_, unop, vari, when) as Constructors -import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Ident, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Vari, _VariRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses -import SqlSquared.Parser (Literal(..), PositionedToken, Token(..), TokenStream, parse, parseModule, parseQuery, prettyParse, printToken, tokenize) as Parser -import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VariRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig +import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Identifier, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Vari, _VariRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses +import SqlSquared.Parser (Literal(..), PositionedToken, parse, parseModule, parseQuery, prettyParse) as Parser +import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), Ident(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VariRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig type Sql = Mu (Sig.SqlF EJ.EJsonF) diff --git a/src/SqlSquared/Constructors.purs b/src/SqlSquared/Constructors.purs index 4aceef4..167c27c 100644 --- a/src/SqlSquared/Constructors.purs +++ b/src/SqlSquared/Constructors.purs @@ -14,7 +14,7 @@ import Matryoshka (class Corecursive, embed) import SqlSquared.Signature as Sig import SqlSquared.Utils ((∘)) -vari ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ String → t +vari ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t vari = embed ∘ Sig.Vari bool ∷ ∀ t. Corecursive t (Sig.SqlF EJsonF) ⇒ Boolean → t @@ -54,7 +54,10 @@ splice ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Maybe t → t splice = embed ∘ Sig.Splice ident ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ String → t -ident = embed ∘ Sig.Ident +ident = ident' ∘ Sig.Ident + +ident' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t +ident' = embed ∘ Sig.Identifier match ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ t → L.List (Sig.Case t) → Maybe t → t match expr cases else_ = embed $ Sig.Match { expr, cases, else_ } @@ -62,10 +65,10 @@ match expr cases else_ = embed $ Sig.Match { expr, cases, else_ } switch ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ L.List (Sig.Case t) → Maybe t → t switch cases else_ = embed $ Sig.Switch { cases, else_ } -let_ ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ String → t → t → t +let_ ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t → t → t let_ id bindTo in_ = embed $ Sig.Let { ident: id, bindTo, in_ } -invokeFunction ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ String → L.List t → t +invokeFunction ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → L.List t → t invokeFunction name args = embed $ Sig.InvokeFunction {name, args} -- when (bool true) # then_ (num 1.0) :P @@ -104,7 +107,10 @@ projection ∷ ∀ t. t → Sig.Projection t projection expr = Sig.Projection {expr, alias: Nothing} as ∷ ∀ t. String → Sig.Projection t → Sig.Projection t -as s (Sig.Projection r) = Sig.Projection r { alias = Just s } +as = as' ∘ Sig.Ident + +as' ∷ ∀ t. Sig.Ident → Sig.Projection t → Sig.Projection t +as' s (Sig.Projection r) = Sig.Projection r { alias = Just s } groupBy ∷ ∀ t f. F.Foldable f ⇒ f t → Sig.GroupBy t groupBy f = Sig.GroupBy { keys: L.fromFoldable f, having: Nothing } diff --git a/src/SqlSquared/Lenses.purs b/src/SqlSquared/Lenses.purs index ff99207..af24c33 100644 --- a/src/SqlSquared/Lenses.purs +++ b/src/SqlSquared/Lenses.purs @@ -10,9 +10,7 @@ import Data.Lens.Iso.Newtype (_Newtype) import Data.List as L import Data.Maybe as M import Data.NonEmpty as NE - import Matryoshka (class Recursive, class Corecursive, embed, project) - import SqlSquared.Signature as S import SqlSquared.Utils (type (×), (∘), (⋙)) @@ -25,7 +23,7 @@ _Case = _Newtype _OrderBy ∷ ∀ a. Iso' (S.OrderBy a) (NE.NonEmpty L.List (S.OrderType × a)) _OrderBy = _Newtype -_Projection ∷ ∀ a. Iso' (S.Projection a) { expr ∷ a, alias ∷ M.Maybe String } +_Projection ∷ ∀ a. Iso' (S.Projection a) { expr ∷ a, alias ∷ M.Maybe S.Ident } _Projection = _Newtype _JoinRelation ∷ ∀ a. Prism' (S.Relation a) (S.JoinRelR a) @@ -193,13 +191,13 @@ _Unop = prism' (embed ∘ S.Unop) $ project ⋙ case _ of S.Unop r → M.Just r _ → M.Nothing -_Ident +_Identifier ∷ ∀ t f . Recursive t (S.SqlF f) ⇒ Corecursive t (S.SqlF f) - ⇒ Prism' t String -_Ident = prism' (embed ∘ S.Ident) $ project ⋙ case _ of - S.Ident s → M.Just s + ⇒ Prism' t S.Ident +_Identifier = prism' (embed ∘ S.Identifier) $ project ⋙ case _ of + S.Identifier s → M.Just s _ → M.Nothing _InvokeFunction @@ -287,7 +285,7 @@ _Vari ∷ ∀ t f . Recursive t (S.SqlF f) ⇒ Corecursive t (S.SqlF f) - ⇒ Prism' t String + ⇒ Prism' t S.Ident _Vari = prism' (embed ∘ S.Vari) $ project ⋙ case _ of S.Vari r → M.Just r _ → M.Nothing diff --git a/src/SqlSquared/Parser.purs b/src/SqlSquared/Parser.purs index 907fe57..79411c1 100644 --- a/src/SqlSquared/Parser.purs +++ b/src/SqlSquared/Parser.purs @@ -30,6 +30,7 @@ import SqlSquared.Constructors as C import SqlSquared.Parser.Tokenizer (Token(..), TokenStream, PositionedToken, tokenize, Literal(..), printToken) import SqlSquared.Path as Pt import SqlSquared.Signature as Sig +import SqlSquared.Signature.Ident (Ident(..)) import SqlSquared.Utils ((∘), type (×), (×)) import Text.Parsing.Parser as P import Text.Parsing.Parser.Combinators as PC @@ -177,7 +178,7 @@ letExpr = do bindTo ← expr operator ";" in_ ← expr - pure $ C.let_ i bindTo in_ + pure $ C.let_ (Ident i) bindTo in_ queryExpr ∷ ∀ m t. SqlParser' m t queryExpr = prod (query <|> definedExpr) queryBinop _BINOP @@ -310,7 +311,7 @@ primaryExpr = asErrorMessage "primary expression" $ PC.choice , wildcard , arrayLiteral , mapLiteral - , ident <#> embed ∘ Sig.Ident + , ident <#> embed ∘ Sig.Identifier ∘ Ident ] caseExpr ∷ ∀ m t. SqlParser' m t @@ -385,7 +386,7 @@ functionExpr ∷ ∀ m t. SqlParser' m t functionExpr = PC.try do name ← ident <|> anyKeyword args ← parenList - pure $ C.invokeFunction (S.toUpper name) args + pure $ C.invokeFunction (Ident (S.toUpper name)) args functionDecl ∷ ∀ m a @@ -401,7 +402,7 @@ functionDecl parseExpr = asErrorMessage "function declaration" do _ ← keyword "begin" body ← parseExpr _ ← keyword "end" - pure $ Sig.FunctionDecl { ident: name, args, body } + pure $ Sig.FunctionDecl { ident: Ident name, args, body } import_ ∷ ∀ m a @@ -416,14 +417,14 @@ import_ = asErrorMessage "import declaration" do variable ∷ ∀ m t. SqlParser' m t variable = C.vari <$> variableString -variableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m String +variableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m Ident variableString = asErrorMessage "variable" $ PC.try do operator ":" PP.Position pos1 ← P.position s ← ident <|> anyKeyword PP.Position pos2 ← P.position guard (pos1.line == pos2.line && pos2.column == pos1.column + 1) - pure s + pure (Ident s) literal ∷ ∀ m t. SqlParser' m t literal = withToken "literal" case _ of @@ -477,7 +478,7 @@ betweenSuffix = do lhs ← defaultExpr _ ← keyword "and" rhs ← defaultExpr - pure \e → C.invokeFunction "BETWEEN" (e : lhs : rhs : L.Nil) + pure \e → C.invokeFunction (Ident "BETWEEN") (e : lhs : rhs : L.Nil) inSuffix ∷ ∀ m t. SqlParser m t (t → t) inSuffix = do @@ -574,7 +575,7 @@ tableRelation = do a ← PC.optionMaybe do _ ← keyword "as" ident - pure $ Sig.TableRelation { alias: a, path } + pure $ Sig.TableRelation { alias: Ident <$> a, path } variRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) variRelation = do @@ -582,7 +583,7 @@ variRelation = do a ← PC.optionMaybe do _ ← keyword "as" ident - pure $ Sig.VariRelation { alias: a, vari } + pure $ Sig.VariRelation { alias: Ident <$> a, vari } exprRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) exprRelation = do @@ -591,7 +592,7 @@ exprRelation = do operator ")" _ ← keyword "as" i ← ident - pure $ Sig.ExprRelation { aliasName: i, expr: e } + pure $ Sig.ExprRelation { alias: Ident i, expr: e } stdJoinRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t → Sig.Relation t) stdJoinRelation = do @@ -682,13 +683,13 @@ projection ∷ ∀ m t. SqlParser m t (Sig.Projection t) projection = do e ← definedExpr a ← PC.optionMaybe (keyword "as" *> ident) - pure $ Sig.Projection { expr: e, alias: a } + pure $ Sig.Projection { expr: e, alias: Ident <$> a } _SEARCH ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ Boolean → t → t → t -_SEARCH b lhs rhs = C.invokeFunction "SEARCH" $ lhs : rhs : (C.bool b) : L.Nil +_SEARCH b lhs rhs = C.invokeFunction (Ident "SEARCH") $ lhs : rhs : (C.bool b) : L.Nil _LIKE ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ Maybe t → t → t → t -_LIKE mbEsc lhs rhs = C.invokeFunction "LIKE" $ lhs : rhs : (fromMaybe (C.string "\\") mbEsc) : L.Nil +_LIKE mbEsc lhs rhs = C.invokeFunction (Ident "LIKE") $ lhs : rhs : (fromMaybe (C.string "\\") mbEsc) : L.Nil _NOT ∷ ∀ t. Corecursive t (Sig.SqlF EJ.EJsonF) ⇒ t → t _NOT = C.unop Sig.Not ∘ C.parens diff --git a/src/SqlSquared/Signature.purs b/src/SqlSquared/Signature.purs index e011968..65f31c9 100644 --- a/src/SqlSquared/Signature.purs +++ b/src/SqlSquared/Signature.purs @@ -56,7 +56,7 @@ import SqlSquared.Path as Pt import SqlSquared.Signature.BinaryOperator (BinaryOperator(..), binopFromString, binopToString, genBinaryOperator, printBinaryOperator) as BO import SqlSquared.Signature.Case (Case(..), genCase, printCase) as CS import SqlSquared.Signature.GroupBy (GroupBy(..), genGroupBy, printGroupBy) as GB -import SqlSquared.Signature.Ident (printIdent) as ID +import SqlSquared.Signature.Ident (Ident(..), printIdent) as ID import SqlSquared.Signature.JoinType (JoinType(..), genJoinType, joinTypeFromString, printJoinType) as JT import SqlSquared.Signature.OrderBy (OrderBy(..), genOrderBy, printOrderBy) as OB import SqlSquared.Signature.OrderType (OrderType(..), genOrderType, orderTypeFromString, printOrderType) as OT @@ -77,7 +77,7 @@ type UnopR a = } type InvokeFunctionR a = - { name ∷ String + { name ∷ ID.Ident , args ∷ L.List a } @@ -93,7 +93,7 @@ type SwitchR a = } type LetR a = - { ident ∷ String + { ident ∷ ID.Ident , bindTo ∷ a , in_ ∷ a } @@ -108,8 +108,8 @@ type SelectR a = } type FunctionDeclR a = - { ident ∷ String - , args ∷ L.List String + { ident ∷ ID.Ident + , args ∷ L.List ID.Ident , body ∷ a } @@ -119,12 +119,12 @@ data SqlF literal a | Splice (Maybe a) | Binop (BinopR a) | Unop (UnopR a) - | Ident String + | Identifier ID.Ident | InvokeFunction (InvokeFunctionR a) | Match (MatchR a) | Switch (SwitchR a) | Let (LetR a) - | Vari String + | Vari ID.Ident | Select (SelectR a) | Parens a @@ -166,7 +166,7 @@ derive instance functorSqlModuleF ∷ Functor SqlModuleF instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where foldMap f = case _ of - Ident _ → mempty + Identifier _ → mempty SetLiteral lst → F.foldMap f lst Splice mbA → F.foldMap f mbA Binop { lhs, rhs } → f lhs <> f rhs @@ -185,7 +185,7 @@ instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where Parens a → f a Literal l → F.foldMap f l foldl f a = case _ of - Ident _ → a + Identifier _ → a SetLiteral lst → F.foldl f a lst Splice mbA → F.foldl f a mbA Binop { lhs, rhs } → f (f a lhs) rhs @@ -212,7 +212,7 @@ instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where Parens p → f a p Literal l → F.foldl f a l foldr f a = case _ of - Ident _ → a + Identifier _ → a SetLiteral lst → F.foldr f a lst Splice mbA → F.foldr f a mbA Binop { lhs, rhs } → f rhs $ f lhs a @@ -269,7 +269,7 @@ instance traversableSqlF ∷ T.Traversable l ⇒ T.Traversable (SqlF l) where map Binop $ { lhs: _, rhs: _, op } <$> f lhs <*> f rhs Unop { op, expr } → map Unop $ { expr: _, op } <$> f expr - Ident s → pure $ Ident s + Identifier s → pure $ Identifier s InvokeFunction { name, args } → map InvokeFunction $ { name, args:_ } <$> T.traverse f args Match { expr, cases, else_ } → @@ -331,10 +331,10 @@ printSqlF printLiteralF = case _ of BO.printBinaryOperator lhs rhs op Unop {expr, op} → UO.printUnaryOperator expr op - Ident s → + Identifier s → ID.printIdent s InvokeFunction {name, args} → - name <> "(" <> F.intercalate ", " args <> ")" + ID.printIdent name <> "(" <> F.intercalate ", " args <> ")" Match { expr, cases, else_ } → "CASE " <> expr @@ -372,7 +372,7 @@ printSqlDeclF = case _ of <> body <> " END" Import path → - "IMPORT " <> ID.printIdent (Pt.printAnyDirPath path) + "IMPORT " <> ID.printIdent (ID.Ident (Pt.printAnyDirPath path)) printSqlQueryF ∷ Algebra SqlQueryF String printSqlQueryF (Query decls expr) = F.intercalate "; " $ L.snoc (printSqlDeclF <$> decls) expr @@ -389,7 +389,7 @@ genSqlF genSqlF genLiteral n | n < 2 = Gen.oneOf $ (Literal <$> genLiteral n) :| - [ map Ident genIdent + [ map Identifier genIdent , map Vari genIdent , pure $ Splice Nothing , pure $ SetLiteral L.Nil @@ -528,11 +528,11 @@ genFunctionDecl n = do genImport ∷ ∀ m a. Gen.MonadGen m ⇒ MonadRec m ⇒ m (SqlDeclF a) genImport = map Import Pt.genAnyDirPath -genIdent ∷ ∀ m. Gen.MonadGen m ⇒ m String +genIdent ∷ ∀ m. Gen.MonadGen m ⇒ m ID.Ident genIdent = do start ← Gen.elements $ "a" :| S.split (S.Pattern "") "bcdefghijklmnopqrstuvwxyz" body ← map (Int.toStringAs Int.hexadecimal) (Gen.chooseInt 0 100000) - pure $ start <> body + pure $ ID.Ident (start <> body) genDecls ∷ ∀ m. Gen.MonadGen m ⇒ MonadRec m ⇒ Int → m (L.List (SqlDeclF Int)) genDecls n = do @@ -614,7 +614,7 @@ genPrimaryExprP n = , genArrayP n , genMapP n , genSpliceP n - , map (embed ∘ Ident) genIdent + , map (embed ∘ Identifier) genIdent ] genCaseP ∷ ∀ m t. Int → GenSql m t diff --git a/src/SqlSquared/Signature/Ident.purs b/src/SqlSquared/Signature/Ident.purs index e4db1c8..22192a4 100644 --- a/src/SqlSquared/Signature/Ident.purs +++ b/src/SqlSquared/Signature/Ident.purs @@ -1,19 +1,33 @@ -module SqlSquared.Signature.Ident where +module SqlSquared.Signature.Ident (Ident(..), printIdent) where import Prelude +import Data.Generic.Rep (class Generic) +import Data.Generic.Rep.Show (genericShow) +import Data.Newtype (class Newtype) import Data.Set as Set import Data.String as S -import Data.String.Regex (test, replace) as Regex -import Data.String.Regex.Flags (ignoreCase, global) as Regex -import Data.String.Regex.Unsafe (unsafeRegex) as Regex +import Data.String.Regex as RX +import Data.String.Regex.Flags as RXF +import Data.String.Regex.Unsafe as RXU import SqlSquared.Parser.Tokenizer (keywords) -printIdent ∷ String → String -printIdent ident = - if Regex.test identifier ident && not (Set.member (S.toLower ident) keywords) - then ident - else "`" <> Regex.replace tick ("\\`") ident <> "`" - where - identifier = Regex.unsafeRegex "^[a-z][_a-z0-9]*$" Regex.ignoreCase - tick = Regex.unsafeRegex "`" Regex.global +newtype Ident = Ident String + +derive newtype instance eqIdent :: Eq Ident +derive newtype instance ordIdent :: Ord Ident +derive instance newtypeIdent :: Newtype Ident _ +derive instance genericIdent :: Generic Ident _ +instance showIdent :: Show Ident where show = genericShow + +printIdent ∷ Ident → String +printIdent (Ident ident) = + if RX.test identifier ident && not (Set.member (S.toLower ident) keywords) + then ident + else "`" <> RX.replace tick ("\\`") ident <> "`" + +identifier ∷ RX.Regex +identifier = RXU.unsafeRegex "^[a-z][_a-z0-9]*$" RXF.ignoreCase + +tick ∷ RX.Regex +tick = RXU.unsafeRegex "`" RXF.global diff --git a/src/SqlSquared/Signature/Projection.purs b/src/SqlSquared/Signature/Projection.purs index 647fe22..0823f10 100644 --- a/src/SqlSquared/Signature/Projection.purs +++ b/src/SqlSquared/Signature/Projection.purs @@ -11,10 +11,10 @@ import Data.Newtype (class Newtype) import Data.String.Gen as GenS import Data.Traversable as T import Matryoshka (Algebra, CoalgebraM) -import SqlSquared.Signature.Ident (printIdent) +import SqlSquared.Signature.Ident (Ident(..), printIdent) import SqlSquared.Utils ((∘)) -newtype Projection a = Projection { expr ∷ a, alias ∷ Maybe String } +newtype Projection a = Projection { expr ∷ a, alias ∷ Maybe Ident } derive instance functorProjection ∷ Functor Projection derive instance newtypeProjection ∷ Newtype (Projection a) _ @@ -36,5 +36,5 @@ printProjection (Projection { expr, alias }) = expr <> F.foldMap (\a → " AS " genProjection ∷ ∀ m. Gen.MonadGen m ⇒ MonadRec m ⇒ CoalgebraM m Projection Int genProjection n = do - alias ← GenC.genMaybe GenS.genUnicodeString + alias ← map Ident <$> GenC.genMaybe GenS.genUnicodeString pure $ Projection { expr: n - 1, alias } diff --git a/src/SqlSquared/Signature/Relation.purs b/src/SqlSquared/Signature/Relation.purs index eb3fabb..1970033 100644 --- a/src/SqlSquared/Signature/Relation.purs +++ b/src/SqlSquared/Signature/Relation.purs @@ -26,17 +26,17 @@ type JoinRelR a = type ExprRelR a = { expr ∷ a - , aliasName ∷ String + , alias ∷ ID.Ident } type VariRelR = - { vari ∷ String - , alias ∷ Maybe String + { vari ∷ ID.Ident + , alias ∷ Maybe ID.Ident } type TableRelR = { path ∷ Either Pt.AnyDir Pt.AnyFile - , alias ∷ Maybe String + , alias ∷ Maybe ID.Ident } data Relation a @@ -73,8 +73,8 @@ instance traversableRelation ∷ T.Traversable Relation where <$> T.traverse f left <*> T.traverse f right <*> f clause - ExprRelation { expr, aliasName} → - (ExprRelation ∘ { expr: _, aliasName}) + ExprRelation { expr, alias } → + (ExprRelation ∘ { expr: _, alias }) <$> f expr VariRelation v → pure $ VariRelation v TableRelation i → pure $ TableRelation i @@ -82,9 +82,9 @@ instance traversableRelation ∷ T.Traversable Relation where printRelation ∷ Algebra Relation String printRelation = case _ of - ExprRelation {expr, aliasName} → - "(" <> expr <> ") AS " <> ID.printIdent aliasName - VariRelation { vari, alias} → + ExprRelation { expr, alias } → + "(" <> expr <> ") AS " <> ID.printIdent alias + VariRelation { vari, alias } → ":" <> ID.printIdent vari <> F.foldMap (\a → " AS " <> ID.printIdent a) alias TableRelation { path, alias } → "`" @@ -115,16 +115,16 @@ genRelation n = ] where genVari = do - vari ← GenS.genUnicodeString - alias ← GenC.genMaybe GenS.genUnicodeString + vari ← ID.Ident <$> GenS.genUnicodeString + alias ← map ID.Ident <$> GenC.genMaybe GenS.genUnicodeString pure $ VariRelation { vari, alias } genTable = do path ← Right <$> Pt.genAnyFilePath - alias ← GenC.genMaybe GenS.genUnicodeString + alias ← map ID.Ident <$> GenC.genMaybe GenS.genUnicodeString pure $ TableRelation { path, alias } genExpr = do - aliasName ← GenS.genUnicodeString - pure $ ExprRelation { aliasName, expr: n - 1 } + alias ← ID.Ident <$> GenS.genUnicodeString + pure $ ExprRelation { alias, expr: n - 1 } genJoin = do joinType ← JT.genJoinType left ← genRelation $ n - 1 diff --git a/test/src/Argonaut.purs b/test/src/Argonaut.purs index 094b9f1..224a18d 100644 --- a/test/src/Argonaut.purs +++ b/test/src/Argonaut.purs @@ -26,7 +26,7 @@ data UnfoldableJC = JC JCursor | S String | I Int jcCoalgebra ∷ Coalgebra (S.SqlF EJsonF) UnfoldableJC jcCoalgebra = case _ of - S s → S.Ident s + S s → S.Identifier (S.Ident s) I i → S.Literal (Integer (HI.fromInt i)) JC cursor → case cursor of JCursorTop → S.Splice Nothing diff --git a/test/src/Gen.purs b/test/src/Gen.purs index fa278ed..47b9b24 100644 --- a/test/src/Gen.purs +++ b/test/src/Gen.purs @@ -5,7 +5,8 @@ import Prelude import Control.Monad.Gen as Gen import Data.Either as E import Effect (Effect) -import SqlSquared (SqlQuery, genSqlQuery, printQuery, tokenize) +import SqlSquared (SqlQuery, genSqlQuery, printQuery) +import SqlSquared.Parser as Parser import Test.QuickCheck as QC import Test.QuickCheck.Arbitrary as A @@ -18,6 +19,6 @@ newtype ParseableSql = ParseableSql SqlQuery test ∷ Effect Unit test = - QC.quickCheck' 1000 \(ArbSql sql) → case tokenize $ printQuery sql of + QC.quickCheck' 1000 \(ArbSql sql) → case Parser.tokenize $ printQuery sql of E.Left err → QC.Failed $ "Tokenizer error: " <> show err <> " \n" <> printQuery sql E.Right _ → QC.Success From de682fee9f233f166a8a501900ee2f57164eaaf2 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 23:48:09 +0100 Subject: [PATCH 4/8] Rename "vari" to "var" --- src/SqlSquared.purs | 6 +++--- src/SqlSquared/Constructors.purs | 4 ++-- src/SqlSquared/Lenses.purs | 12 ++++++------ src/SqlSquared/Parser.purs | 22 +++++++++++----------- src/SqlSquared/Signature.purs | 16 ++++++++-------- src/SqlSquared/Signature/Relation.purs | 22 +++++++++++----------- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/SqlSquared.purs b/src/SqlSquared.purs index 04e9b28..6c03279 100644 --- a/src/SqlSquared.purs +++ b/src/SqlSquared.purs @@ -22,10 +22,10 @@ import Data.Functor.Mu (Mu) import Data.Json.Extended as EJ import Data.Traversable (traverse) import Matryoshka (cata, anaM) -import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, parens, projection, select, set, splice, string, switch, then_, unop, vari, when) as Constructors -import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Identifier, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Vari, _VariRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses +import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, parens, projection, select, set, splice, string, switch, then_, unop, var, when) as Constructors +import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Identifier, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Var, _VarRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses import SqlSquared.Parser (Literal(..), PositionedToken, parse, parseModule, parseQuery, prettyParse) as Parser -import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), Ident(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VariRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig +import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), Ident(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VarRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig type Sql = Mu (Sig.SqlF EJ.EJsonF) diff --git a/src/SqlSquared/Constructors.purs b/src/SqlSquared/Constructors.purs index 167c27c..b5bebb6 100644 --- a/src/SqlSquared/Constructors.purs +++ b/src/SqlSquared/Constructors.purs @@ -14,8 +14,8 @@ import Matryoshka (class Corecursive, embed) import SqlSquared.Signature as Sig import SqlSquared.Utils ((∘)) -vari ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t -vari = embed ∘ Sig.Vari +var ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t +var = embed ∘ Sig.Var bool ∷ ∀ t. Corecursive t (Sig.SqlF EJsonF) ⇒ Boolean → t bool = embed ∘ Sig.Literal ∘ Boolean diff --git a/src/SqlSquared/Lenses.purs b/src/SqlSquared/Lenses.purs index af24c33..9d45fc5 100644 --- a/src/SqlSquared/Lenses.purs +++ b/src/SqlSquared/Lenses.purs @@ -36,9 +36,9 @@ _ExprRelation = prism' S.ExprRelation case _ of S.ExprRelation r → M.Just r _ → M.Nothing -_VariRelation ∷ ∀ a. Prism' (S.Relation a) S.VariRelR -_VariRelation = prism' S.VariRelation case _ of - S.VariRelation r → M.Just r +_VarRelation ∷ ∀ a. Prism' (S.Relation a) S.VarRelR +_VarRelation = prism' S.VarRelation case _ of + S.VarRelation r → M.Just r _ → M.Nothing _TableRelation ∷ ∀ a. Prism' (S.Relation a) S.TableRelR @@ -281,13 +281,13 @@ _BoolLiteral = prism' (embed ∘ S.Literal ∘ EJ.Boolean) $ project ⋙ case _ S.Literal (EJ.Boolean b) → M.Just b _ → M.Nothing -_Vari +_Var ∷ ∀ t f . Recursive t (S.SqlF f) ⇒ Corecursive t (S.SqlF f) ⇒ Prism' t S.Ident -_Vari = prism' (embed ∘ S.Vari) $ project ⋙ case _ of - S.Vari r → M.Just r +_Var = prism' (embed ∘ S.Var) $ project ⋙ case _ of + S.Var r → M.Just r _ → M.Nothing _Select diff --git a/src/SqlSquared/Parser.purs b/src/SqlSquared/Parser.purs index 79411c1..2df9838 100644 --- a/src/SqlSquared/Parser.purs +++ b/src/SqlSquared/Parser.purs @@ -306,7 +306,7 @@ primaryExpr = asErrorMessage "primary expression" $ PC.choice xs → embed $ Sig.SetLiteral xs , unaryOperator , functionExpr - , variable + , varable , literal , wildcard , arrayLiteral @@ -397,7 +397,7 @@ functionDecl parseExpr = asErrorMessage "function declaration" do _ ← PC.try $ keyword "create" *> keyword "function" name ← ident operator "(" - args ← PC.sepBy variableString $ operator "," + args ← PC.sepBy varableString $ operator "," operator ")" _ ← keyword "begin" body ← parseExpr @@ -414,11 +414,11 @@ import_ = asErrorMessage "import declaration" do path ← Pt.parseAnyDirPath P.fail s pure $ Sig.Import path -variable ∷ ∀ m t. SqlParser' m t -variable = C.vari <$> variableString +varable ∷ ∀ m t. SqlParser' m t +varable = C.var <$> varableString -variableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m Ident -variableString = asErrorMessage "variable" $ PC.try do +varableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m Ident +varableString = asErrorMessage "varable" $ PC.try do operator ":" PP.Position pos1 ← P.position s ← ident <|> anyKeyword @@ -557,7 +557,7 @@ relation = do simpleRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) simpleRelation = tableRelation - <|> variRelation + <|> varRelation <|> PC.try exprRelation <|> parenRelation @@ -577,13 +577,13 @@ tableRelation = do ident pure $ Sig.TableRelation { alias: Ident <$> a, path } -variRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) -variRelation = do - vari ← variableString +varRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) +varRelation = do + var ← varableString a ← PC.optionMaybe do _ ← keyword "as" ident - pure $ Sig.VariRelation { alias: Ident <$> a, vari } + pure $ Sig.VarRelation { alias: Ident <$> a, var } exprRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) exprRelation = do diff --git a/src/SqlSquared/Signature.purs b/src/SqlSquared/Signature.purs index 65f31c9..936aa0b 100644 --- a/src/SqlSquared/Signature.purs +++ b/src/SqlSquared/Signature.purs @@ -61,7 +61,7 @@ import SqlSquared.Signature.JoinType (JoinType(..), genJoinType, joinTypeFromStr import SqlSquared.Signature.OrderBy (OrderBy(..), genOrderBy, printOrderBy) as OB import SqlSquared.Signature.OrderType (OrderType(..), genOrderType, orderTypeFromString, printOrderType) as OT import SqlSquared.Signature.Projection (Projection(..), genProjection, printProjection) as PR -import SqlSquared.Signature.Relation (ExprRelR, JoinRelR, Relation(..), TableRelR, VariRelR, genRelation, printRelation) as RL +import SqlSquared.Signature.Relation (ExprRelR, JoinRelR, Relation(..), TableRelR, VarRelR, genRelation, printRelation) as RL import SqlSquared.Signature.UnaryOperator (UnaryOperator(..), genUnaryOperator, printUnaryOperator, unopFromString, unopToString) as UO import SqlSquared.Utils (type (×), (×), (∘), (⋙)) @@ -124,7 +124,7 @@ data SqlF literal a | Match (MatchR a) | Switch (SwitchR a) | Let (LetR a) - | Vari ID.Ident + | Var ID.Ident | Select (SelectR a) | Parens a @@ -175,7 +175,7 @@ instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where Match { expr, cases, else_ } → f expr <> F.foldMap (F.foldMap f) cases <> F.foldMap f else_ Switch { cases, else_} → F.foldMap (F.foldMap f) cases <> F.foldMap f else_ Let { bindTo, in_ } → f bindTo <> f in_ - Vari _ → mempty + Var _ → mempty Select { projections, relations, filter, groupBy, orderBy } → F.foldMap (F.foldMap f) projections <> F.foldMap (F.foldMap f) relations @@ -197,7 +197,7 @@ instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where F.foldl f (F.foldl (F.foldl f) a cases) else_ Let { bindTo, in_} → f (f a bindTo) in_ - Vari _ → a + Var _ → a Select { projections, relations, filter, groupBy, orderBy } → F.foldl (F.foldl f) (F.foldl (F.foldl f) @@ -224,7 +224,7 @@ instance foldableSqlF ∷ F.Foldable l ⇒ F.Foldable (SqlF l) where F.foldr f (F.foldr (flip $ F.foldr f) a cases) else_ Let { bindTo, in_ } → f bindTo $ f in_ a - Vari _ → a + Var _ → a Select { projections, relations, filter, groupBy, orderBy } → F.foldr (flip $ F.foldr f) (F.foldr (flip $ F.foldr f) @@ -288,7 +288,7 @@ instance traversableSqlF ∷ T.Traversable l ⇒ T.Traversable (SqlF l) where $ { bindTo: _, in_: _, ident } <$> f bindTo <*> f in_ - Vari s → pure $ Vari s + Var s → pure $ Var s Parens p → map Parens $ f p Select { isDistinct, projections, relations, filter, groupBy, orderBy } → map Select @@ -349,7 +349,7 @@ printSqlF printLiteralF = case _ of <> " END" Let { ident, bindTo, in_ } → ID.printIdent ident <> " := " <> bindTo <> "; " <> in_ - Vari s → + Var s → ":" <> ID.printIdent s Select { isDistinct, projections, relations, filter, groupBy, orderBy } → "SELECT " @@ -390,7 +390,7 @@ genSqlF genLiteral n | n < 2 = Gen.oneOf $ (Literal <$> genLiteral n) :| [ map Identifier genIdent - , map Vari genIdent + , map Var genIdent , pure $ Splice Nothing , pure $ SetLiteral L.Nil ] diff --git a/src/SqlSquared/Signature/Relation.purs b/src/SqlSquared/Signature/Relation.purs index 1970033..3127092 100644 --- a/src/SqlSquared/Signature/Relation.purs +++ b/src/SqlSquared/Signature/Relation.purs @@ -29,8 +29,8 @@ type ExprRelR a = , alias ∷ ID.Ident } -type VariRelR = - { vari ∷ ID.Ident +type VarRelR = + { var ∷ ID.Ident , alias ∷ Maybe ID.Ident } @@ -42,7 +42,7 @@ type TableRelR = data Relation a = JoinRelation (JoinRelR a) | ExprRelation (ExprRelR a) - | VariRelation VariRelR + | VarRelation VarRelR | TableRelation TableRelR derive instance functorRelation ∷ Functor Relation @@ -76,7 +76,7 @@ instance traversableRelation ∷ T.Traversable Relation where ExprRelation { expr, alias } → (ExprRelation ∘ { expr: _, alias }) <$> f expr - VariRelation v → pure $ VariRelation v + VarRelation v → pure $ VarRelation v TableRelation i → pure $ TableRelation i sequence = T.sequenceDefault @@ -84,8 +84,8 @@ printRelation ∷ Algebra Relation String printRelation = case _ of ExprRelation { expr, alias } → "(" <> expr <> ") AS " <> ID.printIdent alias - VariRelation { vari, alias } → - ":" <> ID.printIdent vari <> F.foldMap (\a → " AS " <> ID.printIdent a) alias + VarRelation { var, alias } → + ":" <> ID.printIdent var <> F.foldMap (\a → " AS " <> ID.printIdent a) alias TableRelation { path, alias } → "`" <> either Pt.printAnyDirPath Pt.printAnyFilePath path @@ -105,19 +105,19 @@ genRelation n = if n < 1 then Gen.oneOf $ genTable :| - [ genVari + [ genVar ] else Gen.oneOf $ genTable :| - [ genVari + [ genVar , genJoin , genExpr ] where - genVari = do - vari ← ID.Ident <$> GenS.genUnicodeString + genVar = do + var ← ID.Ident <$> GenS.genUnicodeString alias ← map ID.Ident <$> GenC.genMaybe GenS.genUnicodeString - pure $ VariRelation { vari, alias } + pure $ VarRelation { var, alias } genTable = do path ← Right <$> Pt.genAnyFilePath alias ← map ID.Ident <$> GenC.genMaybe GenS.genUnicodeString From 99b3a6ac8f67f142cac7c0d7ca5c7c9579c3f854 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 23:53:47 +0100 Subject: [PATCH 5/8] Add primed constructors for record-based arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Basically just save an `embed` elsewhere, but 🤷‍♂️ --- src/SqlSquared/Constructors.purs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/SqlSquared/Constructors.purs b/src/SqlSquared/Constructors.purs index b5bebb6..48656ce 100644 --- a/src/SqlSquared/Constructors.purs +++ b/src/SqlSquared/Constructors.purs @@ -60,16 +60,28 @@ ident' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t ident' = embed ∘ Sig.Identifier match ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ t → L.List (Sig.Case t) → Maybe t → t -match expr cases else_ = embed $ Sig.Match { expr, cases, else_ } +match expr cases else_ = match' { expr, cases, else_ } + +match' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.MatchR t → t +match' = embed ∘ Sig.Match switch ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ L.List (Sig.Case t) → Maybe t → t -switch cases else_ = embed $ Sig.Switch { cases, else_ } +switch cases else_ = switch' { cases, else_ } + +switch' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.SwitchR t → t +switch' = embed ∘ Sig.Switch let_ ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → t → t → t let_ id bindTo in_ = embed $ Sig.Let { ident: id, bindTo, in_ } +let' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.LetR t → t +let' = embed ∘ Sig.Let + invokeFunction ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.Ident → L.List t → t -invokeFunction name args = embed $ Sig.InvokeFunction {name, args} +invokeFunction name args = invokeFunction' { name, args } + +invokeFunction' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.InvokeFunctionR t → t +invokeFunction' = embed ∘ Sig.InvokeFunction -- when (bool true) # then_ (num 1.0) :P when ∷ ∀ t. t → (t → Sig.Case t) @@ -90,8 +102,7 @@ select → Maybe (Sig.OrderBy t) → t select isDistinct projections relations filter gb orderBy = - embed - $ Sig.Select + select' { isDistinct , projections: L.fromFoldable projections , relations @@ -100,6 +111,8 @@ select isDistinct projections relations filter gb orderBy = , orderBy } +select' ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ Sig.SelectR t → t +select' = embed ∘ Sig.Select -- project (ident "foo") # as "bar" -- project (ident "foo") @@ -120,9 +133,8 @@ having t (Sig.GroupBy r) = Sig.GroupBy r{ having = Just t } buildSelect ∷ ∀ t f. Corecursive t (Sig.SqlF f) ⇒ (Sig.SelectR t → Sig.SelectR t) → t buildSelect f = - embed - $ Sig.Select - $ f { isDistinct: false + select' $ + f { isDistinct: false , projections: L.Nil , relations: Nothing , filter: Nothing From 60ec0e12454e09edf12e3cb04cb79ddf8f263403 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Thu, 26 Jul 2018 23:57:38 +0100 Subject: [PATCH 6/8] Update constructor re-exports --- src/SqlSquared.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SqlSquared.purs b/src/SqlSquared.purs index 6c03279..70bc0b7 100644 --- a/src/SqlSquared.purs +++ b/src/SqlSquared.purs @@ -22,7 +22,7 @@ import Data.Functor.Mu (Mu) import Data.Json.Extended as EJ import Data.Traversable (traverse) import Matryoshka (cata, anaM) -import SqlSquared.Constructors (array, as, binop, bool, buildSelect, groupBy, having, hugeNum, ident, int, invokeFunction, let_, map_, match, null, num, parens, projection, select, set, splice, string, switch, then_, unop, var, when) as Constructors +import SqlSquared.Constructors (array, as, as', binop, bool, buildSelect, groupBy, having, hugeNum, ident, ident', int, invokeFunction, invokeFunction', let', let_, map_, match, match', null, num, parens, projection, select, select', set, splice, string, switch, switch', then_, unop, var, when) as Constructors import SqlSquared.Lenses (_ArrayLiteral, _Binop, _BoolLiteral, _Case, _DecimalLiteral, _ExprRelation, _GroupBy, _Identifier, _IntLiteral, _InvokeFunction, _JoinRelation, _Let, _Literal, _MapLiteral, _Match, _NullLiteral, _OrderBy, _Parens, _Projection, _Select, _SetLiteral, _Splice, _StringLiteral, _Switch, _TableRelation, _Unop, _Var, _VarRelation, _alias, _aliasName, _args, _bindTo, _cases, _clause, _cond, _else, _expr, _filter, _groupBy, _having, _ident, _in, _isDistinct, _joinType, _keys, _left, _lhs, _name, _op, _orderBy, _projections, _relations, _rhs, _right, _tablePath) as Lenses import SqlSquared.Parser (Literal(..), PositionedToken, parse, parseModule, parseQuery, prettyParse) as Parser import SqlSquared.Signature (type (×), BinaryOperator(..), BinopR, Case(..), ExprRelR, FunctionDeclR, GroupBy(..), Ident(..), InvokeFunctionR, JoinRelR, JoinType(..), LetR, MatchR, OrderBy(..), OrderType(..), Projection(..), Relation(..), SelectR, SqlDeclF(..), SqlF(..), SqlModuleF(..), SqlQueryF(..), SwitchR, TableRelR, UnaryOperator(..), UnopR, VarRelR, binopFromString, binopToString, genBinaryOperator, genCase, genGroupBy, genJoinType, genOrderBy, genOrderType, genProjection, genRelation, genSqlDeclF, genSqlF, genSqlModuleF, genSqlQueryF, genUnaryOperator, joinTypeFromString, orderTypeFromString, printBinaryOperator, printCase, printGroupBy, printIdent, printJoinType, printOrderBy, printOrderType, printProjection, printRelation, printSqlDeclF, printSqlF, printSqlModuleF, printSqlQueryF, printUnaryOperator, unopFromString, unopToString, (×), (∘), (⋙)) as Sig From 26178e2ee2e390e1f6ec6242c65aa0a3475c8ff8 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Fri, 27 Jul 2018 02:07:30 +0100 Subject: [PATCH 7/8] Fix 'varable' naming mistake --- src/SqlSquared/Parser.purs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/SqlSquared/Parser.purs b/src/SqlSquared/Parser.purs index 2df9838..d23dce0 100644 --- a/src/SqlSquared/Parser.purs +++ b/src/SqlSquared/Parser.purs @@ -306,7 +306,7 @@ primaryExpr = asErrorMessage "primary expression" $ PC.choice xs → embed $ Sig.SetLiteral xs , unaryOperator , functionExpr - , varable + , variable , literal , wildcard , arrayLiteral @@ -397,7 +397,7 @@ functionDecl parseExpr = asErrorMessage "function declaration" do _ ← PC.try $ keyword "create" *> keyword "function" name ← ident operator "(" - args ← PC.sepBy varableString $ operator "," + args ← PC.sepBy variableString $ operator "," operator ")" _ ← keyword "begin" body ← parseExpr @@ -414,11 +414,11 @@ import_ = asErrorMessage "import declaration" do path ← Pt.parseAnyDirPath P.fail s pure $ Sig.Import path -varable ∷ ∀ m t. SqlParser' m t -varable = C.var <$> varableString +variable ∷ ∀ m t. SqlParser' m t +variable = C.var <$> variableString -varableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m Ident -varableString = asErrorMessage "varable" $ PC.try do +variableString ∷ ∀ m. Monad m ⇒ P.ParserT TokenStream m Ident +variableString = asErrorMessage "variable" $ PC.try do operator ":" PP.Position pos1 ← P.position s ← ident <|> anyKeyword @@ -579,7 +579,7 @@ tableRelation = do varRelation ∷ ∀ m t. SqlParser m t (Sig.Relation t) varRelation = do - var ← varableString + var ← variableString a ← PC.optionMaybe do _ ← keyword "as" ident From da0f12b8bc03600b19737a6149cbe9cd1d684158 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Fri, 27 Jul 2018 11:04:18 +0100 Subject: [PATCH 8/8] Move genIdent to live with Ident --- src/SqlSquared/Signature.purs | 26 +++++++++----------------- src/SqlSquared/Signature/Ident.purs | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/SqlSquared/Signature.purs b/src/SqlSquared/Signature.purs index 936aa0b..f88f0ba 100644 --- a/src/SqlSquared/Signature.purs +++ b/src/SqlSquared/Signature.purs @@ -41,14 +41,12 @@ import Data.Eq (class Eq1) import Data.Foldable as F import Data.HugeInt as HI import Data.HugeNum as HN -import Data.Int as Int import Data.Json.Extended as EJ import Data.List as L import Data.Maybe (Maybe(..)) import Data.Newtype (class Newtype) import Data.NonEmpty ((:|)) import Data.Ord (class Ord1) -import Data.String as S import Data.String.Gen as GenS import Data.Traversable as T import Matryoshka (Algebra, CoalgebraM, class Corecursive, embed) @@ -56,7 +54,7 @@ import SqlSquared.Path as Pt import SqlSquared.Signature.BinaryOperator (BinaryOperator(..), binopFromString, binopToString, genBinaryOperator, printBinaryOperator) as BO import SqlSquared.Signature.Case (Case(..), genCase, printCase) as CS import SqlSquared.Signature.GroupBy (GroupBy(..), genGroupBy, printGroupBy) as GB -import SqlSquared.Signature.Ident (Ident(..), printIdent) as ID +import SqlSquared.Signature.Ident (Ident(..), genIdent, printIdent) as ID import SqlSquared.Signature.JoinType (JoinType(..), genJoinType, joinTypeFromString, printJoinType) as JT import SqlSquared.Signature.OrderBy (OrderBy(..), genOrderBy, printOrderBy) as OB import SqlSquared.Signature.OrderType (OrderType(..), genOrderType, orderTypeFromString, printOrderType) as OT @@ -389,8 +387,8 @@ genSqlF genSqlF genLiteral n | n < 2 = Gen.oneOf $ (Literal <$> genLiteral n) :| - [ map Identifier genIdent - , map Var genIdent + [ map Identifier ID.genIdent + , map Var ID.genIdent , pure $ Splice Nothing , pure $ SetLiteral L.Nil ] @@ -437,7 +435,7 @@ genUnop n = do genInvokeFunction ∷ ∀ m l. Gen.MonadGen m ⇒ CoalgebraM m (SqlF l) Int genInvokeFunction n = do - name ← genIdent + name ← ID.genIdent len ← Gen.chooseInt 0 $ n - 1 pure $ InvokeFunction { name, args: map (const $ n - 1) $ L.range 0 len } @@ -469,7 +467,7 @@ genSwitch n = do genLet ∷ ∀ m l. Gen.MonadGen m ⇒ CoalgebraM m (SqlF l) Int genLet n = do - ident ← genIdent + ident ← ID.genIdent pure $ Let { ident , bindTo: n - 1 , in_: n - 1 @@ -516,11 +514,11 @@ genSelect n = do genFunctionDecl ∷ ∀ m. Gen.MonadGen m ⇒ CoalgebraM m SqlDeclF Int genFunctionDecl n = do - ident ← genIdent + ident ← ID.genIdent len ← Gen.chooseInt 0 $ n - 1 let foldFn acc _ = do - arg ← genIdent + arg ← ID.genIdent pure $ arg L.: acc args ← L.foldM foldFn L.Nil $ L.range 0 len pure $ FunctionDecl { ident, args, body: n - 1 } @@ -528,12 +526,6 @@ genFunctionDecl n = do genImport ∷ ∀ m a. Gen.MonadGen m ⇒ MonadRec m ⇒ m (SqlDeclF a) genImport = map Import Pt.genAnyDirPath -genIdent ∷ ∀ m. Gen.MonadGen m ⇒ m ID.Ident -genIdent = do - start ← Gen.elements $ "a" :| S.split (S.Pattern "") "bcdefghijklmnopqrstuvwxyz" - body ← map (Int.toStringAs Int.hexadecimal) (Gen.chooseInt 0 100000) - pure $ ID.Ident (start <> body) - genDecls ∷ ∀ m. Gen.MonadGen m ⇒ MonadRec m ⇒ Int → m (L.List (SqlDeclF Int)) genDecls n = do let @@ -568,7 +560,7 @@ genLeaf = genLetP ∷ ∀ m t. Int → GenSql m t genLetP n = do - ident ← genIdent + ident ← ID.genIdent bindTo ← genSql n in_ ← genSql n pure $ embed $ Let { ident, bindTo, in_ } @@ -614,7 +606,7 @@ genPrimaryExprP n = , genArrayP n , genMapP n , genSpliceP n - , map (embed ∘ Identifier) genIdent + , map (embed ∘ Identifier) ID.genIdent ] genCaseP ∷ ∀ m t. Int → GenSql m t diff --git a/src/SqlSquared/Signature/Ident.purs b/src/SqlSquared/Signature/Ident.purs index 22192a4..0b166d8 100644 --- a/src/SqlSquared/Signature/Ident.purs +++ b/src/SqlSquared/Signature/Ident.purs @@ -1,10 +1,17 @@ -module SqlSquared.Signature.Ident (Ident(..), printIdent) where +module SqlSquared.Signature.Ident + ( Ident(..) + , printIdent + , genIdent + ) where import Prelude +import Control.Monad.Gen as Gen import Data.Generic.Rep (class Generic) import Data.Generic.Rep.Show (genericShow) +import Data.Int as Int import Data.Newtype (class Newtype) +import Data.NonEmpty ((:|)) import Data.Set as Set import Data.String as S import Data.String.Regex as RX @@ -31,3 +38,9 @@ identifier = RXU.unsafeRegex "^[a-z][_a-z0-9]*$" RXF.ignoreCase tick ∷ RX.Regex tick = RXU.unsafeRegex "`" RXF.global + +genIdent ∷ ∀ m. Gen.MonadGen m ⇒ m Ident +genIdent = do + start ← Gen.elements $ "a" :| S.split (S.Pattern "") "bcdefghijklmnopqrstuvwxyz" + body ← map (Int.toStringAs Int.hexadecimal) (Gen.chooseInt 0 100000) + pure $ Ident (start <> body)