content: 
  -- | The AST for SQL.
  {-# LANGUAGE DeriveDataTypeable #-}
  module Language.SQL.SimpleSQL.Syntax
      (-- * Scalar expressions
       ScalarExpr(..)
      ,Name(..)
      ,TypeName(..)
      ,IntervalTypeField(..)
      ,Sign(..)
      ,PrecMultiplier(..)
      ,PrecUnits(..)
      ,SetQuantifier(..)
      ,SortSpec(..)
      ,Direction(..)
      ,NullsOrder(..)
      ,InPredValue(..)
      ,SubQueryExprType(..)
      ,CompPredQuantifier(..)
      ,Frame(..)
      ,FrameRows(..)
      ,FramePos(..)
      ,OdbcLiteralType(..)
       -- * Query expressions
      ,QueryExpr(..)
      ,SetOperatorName(..)
      ,Corresponding(..)
      ,Alias(..)
      ,GroupingExpr(..)
       -- ** From
      ,TableRef(..)
      ,JoinType(..)
      ,JoinCondition(..)
       -- * Statements
      ,Statement(..)
      ,DropBehaviour(..)
      ,IdentityRestart(..)
      ,InsertSource(..)
      ,SetClause(..)
      ,TableElement(..)
      ,ColumnDef(..)
      ,DefaultClause(..)
      ,IdentityWhen(..)
      ,SequenceGeneratorOption(..)
      ,ColConstraintDef(..)
      ,AutoincrementClause
      ,ColConstraint(..)
      ,TableConstraint(..)
      ,ReferenceMatch(..)
      ,ReferentialAction(..)
      ,AlterTableAction(..)
      ,CheckOption(..)
      ,AlterDomainAction(..)
      ,AdminOption(..)
      ,GrantOption(..)
      ,PrivilegeObject(..)
      ,PrivilegeAction(..)
      ,AdminOptionFor(..)
      ,GrantOptionFor(..)
       -- * Comment
      ,Comment(..)
  
      ,makeSelect
      ,toQueryExpr
      ,MakeSelect(..)
      ) where
  
  import Data.Text (Text)
  
  import Data.Data (Data, Typeable)
  
  -- | Represents a value expression. This is used for the expressions
  -- in select lists. It is also used for expressions in where, group
  -- by, having, order by and so on.
  data ScalarExpr
      = -- | a numeric literal optional decimal point, e+-
        -- integral exponent, e.g
        --
        -- * 10
        --
        -- * 10.
        --
        -- * .1
        --
        -- * 10.1
        --
        -- * 1e5
        --
        -- * 12.34e-6
        NumLit Text
        -- | string literal, with the start and end quote
        -- e.g. 'test' -> TextLit "'" "'" "test"
      | StringLit Text Text Text
        -- | text of interval literal, units of interval precision,
        -- e.g. interval 3 days (3)
      | IntervalLit
        {ilSign :: Maybe Sign -- ^ if + or - used
        ,ilLiteral :: Text -- ^ literal text
        ,ilFrom :: IntervalTypeField
        ,ilTo :: Maybe IntervalTypeField
        }
  
        -- | prefix 'typed literal', e.g. int '42'
      | TypedLit TypeName Text
  
        -- | identifier with parts separated by dots
      | Iden [Name]
        -- | 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
      | HostParameter Text (Maybe Text) -- ^ represents a host
                                            -- parameter, e.g. :a. The
                                            -- Maybe Text is for the
                                            -- indicator, e.g. :var
                                            -- indicator :nl
  
  
        -- | Infix binary operators. This is used for symbol operators
        -- (a + b), keyword operators (a and b) and multiple keyword
        -- operators (a is similar to b)
      | BinOp ScalarExpr [Name] ScalarExpr
        -- | Prefix unary operators. This is used for symbol
        -- operators, keyword operators and multiple keyword operators.
      | PrefixOp [Name] ScalarExpr
        -- | Postfix unary operators. This is used for symbol
        -- operators, keyword operators and multiple keyword operators.
      | PostfixOp [Name] ScalarExpr
        -- | Used for ternary, mixfix and other non orthodox
        -- operators. Currently used for row constructors, and for
        -- between.
      | SpecialOp [Name] [ScalarExpr]
  
        -- | function application (anything that looks like c style
        -- function application syntactically)
      | App [Name] [ScalarExpr]
  
  
        -- | aggregate application, which adds distinct or all, and
        -- order by, to regular function application
      | AggregateApp
        {aggName :: [Name] -- ^ aggregate function name
        ,aggDistinct :: SetQuantifier -- ^ distinct
        ,aggArgs :: [ScalarExpr]-- ^ args
        ,aggOrderBy :: [SortSpec] -- ^ order by
        ,aggFilter :: Maybe ScalarExpr -- ^ filter
        }
        -- | aggregates with within group
      | AggregateAppGroup
        {aggName :: [Name] -- ^ aggregate function name
        ,aggArgs :: [ScalarExpr] -- ^ args
        ,aggGroup :: [SortSpec] -- ^ within group
        }
        -- | window application, which adds over (partition by a order
        -- by b) to regular function application. Explicit frames are
        -- not currently supported
      | WindowApp
        {wnName :: [Name] -- ^ window function name
        ,wnArgs :: [ScalarExpr] -- ^ args
        ,wnPartition :: [ScalarExpr] -- ^ partition by
        ,wnOrderBy :: [SortSpec] -- ^ order by
        ,wnFrame :: Maybe Frame -- ^ frame clause
        }
  
        -- | Used for the operators which look like functions
        -- except the arguments are separated by keywords instead
        -- of commas. The maybe is for the first unnamed argument
        -- if it is present, and the list is for the keyword argument
        -- pairs.
      | SpecialOpK [Name] (Maybe ScalarExpr) [(Text,ScalarExpr)]
  
        -- | cast(a as typename)
      | Cast ScalarExpr TypeName
  
        -- | convert expression to given datatype @CONVERT(data_type(length), expression, style)@
      | Convert TypeName ScalarExpr (Maybe Integer)
  
        -- | case expression. both flavours supported
      | Case
        {caseTest :: Maybe ScalarExpr -- ^ test value
        ,caseWhens :: [([ScalarExpr],ScalarExpr)] -- ^ when branches
        ,caseElse :: Maybe ScalarExpr -- ^ else value
        }
  
      | Parens ScalarExpr
  
        -- | in list literal and in subquery, if the bool is false it
        -- means not in was used ('a not in (1,2)')
      | In Bool ScalarExpr InPredValue
  
        -- | exists, all, any, some subqueries
      | SubQueryExpr SubQueryExprType QueryExpr
  
      | QuantifiedComparison
              ScalarExpr
              [Name] -- operator
              CompPredQuantifier
              QueryExpr
  
      | Match ScalarExpr Bool -- true if unique
            QueryExpr
      | Array ScalarExpr [ScalarExpr] -- ^ represents an array
                                    -- access expression, or an array ctor
                                    -- e.g. a[3]. The first
                                    -- scalarExpr is the array, the
                                    -- second is the subscripts/ctor args
      | ArrayCtor QueryExpr -- ^ this is used for the query expression version of array constructors, e.g. array(select * from t)
  
  {-
  todo: special syntax for like, similar with escape - escape cannot go
  in other places
  -}
  
      --  | Escape ScalarExpr Char
      --  | UEscape ScalarExpr Char
      | Collate ScalarExpr [Name]
      | MultisetBinOp ScalarExpr SetOperatorName SetQuantifier ScalarExpr
      | MultisetCtor [ScalarExpr]
      | MultisetQueryCtor QueryExpr
      | NextValueFor [Name]
      | VEComment [Comment] ScalarExpr
      | OdbcLiteral OdbcLiteralType Text
        -- ^ an odbc literal e.g. {d '2000-01-01'}
      | OdbcFunc ScalarExpr
        -- ^ an odbc function call e.g. {fn CHARACTER_LENGTH('test')}
        deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents an identifier name, which can be quoted or unquoted.
  -- examples:
  --
  -- * test -> Name Nothing "test"
  -- * "test" -> Name (Just "\"","\"") "test"
  -- * `something` -> Name (Just ("`","`") "something"
  -- * [ms] -> Name (Just ("[","]") "ms"
  data Name = Name (Maybe (Text,Text)) Text
              deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents a type name, used in casts.
  data TypeName
      = TypeName [Name]
      | PrecTypeName [Name] Integer
      | PrecScaleTypeName [Name] Integer Integer
      | PrecLengthTypeName [Name] Integer (Maybe PrecMultiplier) (Maybe PrecUnits)
        -- precision, characterset, collate
      | CharTypeName [Name] (Maybe Integer) [Name] [Name]
      | TimeTypeName [Name] (Maybe Integer) Bool -- true == with time zone
      | RowTypeName [(Name,TypeName)]
      | IntervalTypeName IntervalTypeField (Maybe IntervalTypeField)
      | ArrayTypeName TypeName (Maybe Integer)
      | MultisetTypeName TypeName
        deriving (Eq,Show,Read,Data,Typeable)
  
  data IntervalTypeField = Itf Text (Maybe (Integer, Maybe Integer))
                           deriving (Eq,Show,Read,Data,Typeable)
  
  data Sign = Plus | Minus
              deriving (Eq,Show,Read,Data,Typeable)
  
  data PrecMultiplier = PrecK | PrecM | PrecG | PrecT | PrecP
                        deriving (Eq,Show,Read,Data,Typeable)
  data PrecUnits = PrecCharacters
                 | PrecOctets
                  deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Used for 'expr in (scalar expression list)', and 'expr in
  -- (subquery)' syntax.
  data InPredValue = InList [ScalarExpr]
                   | InQueryExpr QueryExpr
                     deriving (Eq,Show,Read,Data,Typeable)
  
  -- not sure if scalar subquery, exists and unique should be represented like this
  
  -- | A subquery in a scalar expression.
  data SubQueryExprType
      = -- | exists (query expr)
        SqExists
        -- | unique (query expr)
      | SqUnique
        -- | a scalar subquery
      | SqSq
        deriving (Eq,Show,Read,Data,Typeable)
  
  data CompPredQuantifier
      = CPAny
      | CPSome
      | CPAll
        deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents one field in an order by list.
  data SortSpec = SortSpec ScalarExpr Direction NullsOrder
                  deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents 'nulls first' or 'nulls last' in an order by clause.
  data NullsOrder = NullsOrderDefault
                  | NullsFirst
                  | NullsLast
                    deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents the frame clause of a window
  -- this can be [range | rows] frame_start
  -- or [range | rows] between frame_start and frame_end
  data Frame = FrameFrom FrameRows FramePos
             | FrameBetween FrameRows FramePos FramePos
               deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents whether a window frame clause is over rows or ranges.
  data FrameRows = FrameRows | FrameRange
                   deriving (Eq,Show,Read,Data,Typeable)
  
  -- | represents the start or end of a frame
  data FramePos = UnboundedPreceding
                | Preceding ScalarExpr
                | Current
                | Following ScalarExpr
                | UnboundedFollowing
                  deriving (Eq,Show,Read,Data,Typeable)
  
  
  -- | the type of an odbc literal (e.g. {d '2000-01-01'}),
  -- correpsonding to the letter after the opening {
  data OdbcLiteralType = OLDate
                       | OLTime
                       | OLTimestamp
                         deriving (Eq,Show,Read,Data,Typeable)
  
  
  -- | Represents a query expression, which can be:
  --
  -- * a regular select;
  --
  -- * a set operator (union, except, intersect);
  --
  -- * a common table expression (with);
  --
  -- * a table value constructor (values (1,2),(3,4)); or
  --
  -- * an explicit table (table t).
  data QueryExpr
      = Select
        {qeSetQuantifier :: SetQuantifier
        ,qeSelectList :: [(ScalarExpr,Maybe Name)]
         -- ^ the expressions and the column aliases
  
  {-
  TODO: consider breaking this up. The SQL grammar has
  queryexpr = select <select list> [<table expression>]
  table expression = <from> [where] [groupby] [having] ...
  
  This would make some things a bit cleaner?
  -}
  
        ,qeFrom :: [TableRef]
        ,qeWhere :: Maybe ScalarExpr
        ,qeGroupBy :: [GroupingExpr]
        ,qeHaving :: Maybe ScalarExpr
        ,qeOrderBy :: [SortSpec]
        ,qeOffset :: Maybe ScalarExpr
        ,qeFetchFirst :: Maybe ScalarExpr
        }
      | QueryExprSetOp
        {qe0 :: QueryExpr
        ,qeCombOp :: SetOperatorName
        ,qeSetQuantifier :: SetQuantifier
        ,qeCorresponding :: Corresponding
        ,qe1 :: QueryExpr
        }
      | With
        {qeWithRecursive :: Bool
        ,qeViews :: [(Alias,QueryExpr)]
        ,qeQueryExpression :: QueryExpr}
      | Values [[ScalarExpr]]
      | Table [Name]
      | QueryExprParens QueryExpr
      | QEComment [Comment] QueryExpr
        deriving (Eq,Show,Read,Data,Typeable)
  
  {-
  TODO: add queryexpr parens to deal with e.g.
  (select 1 union select 2) union select 3
  I'm not sure if this is valid syntax or not.
  -}
  
  -- | Represents the Distinct or All keywords, which can be used
  -- before a select list, in an aggregate/window function
  -- application, or in a query expression set operator.
  data SetQuantifier = SQDefault | Distinct | All deriving (Eq,Show,Read,Data,Typeable)
  
  -- | The direction for a column in order by.
  data Direction = DirDefault | Asc | Desc deriving (Eq,Show,Read,Data,Typeable)
  -- | Query expression set operators.
  data SetOperatorName = Union | Except | Intersect deriving (Eq,Show,Read,Data,Typeable)
  -- | Corresponding, an option for the set operators.
  data Corresponding = Corresponding | Respectively deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents an item in a group by clause.
  data GroupingExpr
      = GroupingParens [GroupingExpr]
      | Cube [GroupingExpr]
      | Rollup [GroupingExpr]
      | GroupingSets [GroupingExpr]
      | SimpleGroup ScalarExpr
        deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents a entry in the csv of tables in the from clause.
  data TableRef = -- | from t / from s.t
                  TRSimple [Name]
                  -- | from a join b, the bool is true if natural was used
                | TRJoin TableRef Bool JoinType TableRef (Maybe JoinCondition)
                  -- | from (a)
                | TRParens TableRef
                  -- | from a as b(c,d)
                | TRAlias TableRef Alias
                  -- | from (query expr)
                | TRQueryExpr QueryExpr
                  -- | from function(args)
                | TRFunction [Name] [ScalarExpr]
                  -- | from lateral t
                | TRLateral TableRef
                  -- | ODBC {oj t1 left outer join t2 on expr} syntax
                | TROdbc TableRef
                  deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Represents an alias for a table valued expression, used in with
  -- queries and in from alias, e.g. select a from t u, select a from t u(b),
  -- with a(c) as select 1, select * from a.
  data Alias = Alias Name (Maybe [Name])
               deriving (Eq,Show,Read,Data,Typeable)
  
  -- | The type of a join.
  data JoinType = JInner | JLeft | JRight | JFull | JCross
                  deriving (Eq,Show,Read,Data,Typeable)
  
  -- | The join condition.
  data JoinCondition = JoinOn ScalarExpr -- ^ on expr
                     | JoinUsing [Name] -- ^ using (column list)
                       deriving (Eq,Show,Read,Data,Typeable)
  
  -- ---------------------------
  
  data Statement =
      -- ddl
      CreateSchema [Name]
    | DropSchema [Name] DropBehaviour
    | CreateTable [Name] [TableElement] Bool
    | AlterTable [Name] AlterTableAction
    | DropTable [Name] DropBehaviour
    | CreateIndex Bool [Name] [Name] [Name]
    | CreateView Bool [Name] (Maybe [Name])
          QueryExpr (Maybe CheckOption)
    | DropView [Name]  DropBehaviour
    | CreateDomain [Name] TypeName (Maybe ScalarExpr)
         [(Maybe [Name], ScalarExpr)]
    | AlterDomain [Name] AlterDomainAction
    | DropDomain [Name] DropBehaviour
  
      -- probably won't do character sets, collations
      -- and translations because I think they are too far from
      -- reality
    {-  | CreateCharacterSet
    | DropCharacterSet
    | CreateCollation
    | DropCollation
    | CreateTranslation
    | DropTranslation -}
    | CreateAssertion [Name] ScalarExpr
    | DropAssertion [Name] DropBehaviour
    {-   | CreateTrigger
    | DropTrigger
    | CreateType
    | AlterType
    | DropType
      -- routine stuff? TODO
    | CreateCast
    | DropCast
    | CreateOrdering
    | DropOrdering -}
      -- transforms
    | CreateSequence [Name] [SequenceGeneratorOption]
    | AlterSequence [Name] [SequenceGeneratorOption]
    | DropSequence [Name] DropBehaviour
      -- dml
    | SelectStatement QueryExpr
    {-    | DeclareCursor
    | OpenCursor
    | FetchCursor
    | CloseCursor
    | SelectInto -}
    --   | DeletePositioned
    | Delete [Name] (Maybe Name) (Maybe ScalarExpr)
    | Truncate [Name] IdentityRestart
    | Insert [Name] (Maybe [Name]) InsertSource
    --  | Merge
    | Update [Name] (Maybe Name) [SetClause] (Maybe ScalarExpr)
    {-  | TemporaryTable
    | FreeLocator
    | HoldLocator  -}
      -- access control
    | GrantPrivilege [PrivilegeAction] PrivilegeObject [Name] GrantOption
    | GrantRole [Name] [Name] AdminOption
    | CreateRole Name
    | DropRole Name
    | RevokePrivilege GrantOptionFor [PrivilegeAction] PrivilegeObject
              [Name] DropBehaviour
    | RevokeRole AdminOptionFor [Name] [Name] DropBehaviour
      -- transaction management
    | StartTransaction
    --  | SetTransaction
    --  | SetContraints
    | Savepoint Name
    | ReleaseSavepoint Name
    | Commit
    | Rollback (Maybe Name)
      -- session
    {-  | SetSessionCharacteristics
    | SetSessionAuthorization
    | SetRole
    | SetTimeZone
    | SetCatalog
    | SetSchema
    | SetNames
    | SetTransform
    | SetCollation -}
    | StatementComment [Comment]
    | EmptyStatement
      deriving (Eq,Show,Read,Data,Typeable)
  
  data DropBehaviour =
      Restrict
    | Cascade
    | DefaultDropBehaviour
      deriving (Eq,Show,Read,Data,Typeable)
  
  data IdentityRestart =
      ContinueIdentity
    | RestartIdentity
    | DefaultIdentityRestart
      deriving (Eq,Show,Read,Data,Typeable)
  
  data InsertSource =
      InsertQuery QueryExpr
    | DefaultInsertValues
      deriving (Eq,Show,Read,Data,Typeable)
  
  data SetClause =
      Set [Name] ScalarExpr
    | SetMultiple [[Name]] [ScalarExpr]
      deriving (Eq,Show,Read,Data,Typeable)
  
  data TableElement =
      TableColumnDef ColumnDef
    | TableConstraintDef (Maybe [Name]) TableConstraint
      deriving (Eq,Show,Read,Data,Typeable)
  
  data ColumnDef = ColumnDef Name (Maybe TypeName)
         [ColConstraintDef]
         -- (Maybe CollateClause)
      deriving (Eq,Show,Read,Data,Typeable)
  
  data ColConstraintDef =
      ColConstraintDef (Maybe [Name]) ColConstraint
        -- (Maybe [ConstraintCharacteristics])
      deriving (Eq,Show,Read,Data,Typeable)
  
  type AutoincrementClause = Bool
  
  data ColConstraint =
      ColNullableConstraint
    | ColNotNullConstraint
    | ColUniqueConstraint
    | ColPrimaryKeyConstraint AutoincrementClause
    | ColReferencesConstraint [Name] (Maybe Name)
         ReferenceMatch
         ReferentialAction
         ReferentialAction
    | ColCheckConstraint ScalarExpr
    | ColDefaultClause DefaultClause
      deriving (Eq,Show,Read,Data,Typeable)
  
  data TableConstraint =
      TableUniqueConstraint [Name]
    | TablePrimaryKeyConstraint [Name]
    | TableReferencesConstraint [Name] [Name] (Maybe [Name])
         ReferenceMatch
         ReferentialAction
         ReferentialAction
    | TableCheckConstraint ScalarExpr
      deriving (Eq,Show,Read,Data,Typeable)
  
  
  data ReferenceMatch =
      DefaultReferenceMatch
    | MatchFull
    | MatchPartial
    | MatchSimple
      deriving (Eq,Show,Read,Data,Typeable)
  
  data ReferentialAction =
      DefaultReferentialAction
    | RefCascade
    | RefSetNull
    | RefSetDefault
    | RefRestrict
    | RefNoAction
      deriving (Eq,Show,Read,Data,Typeable)
  
  data AlterTableAction =
      AddColumnDef ColumnDef
    | AlterColumnSetDefault Name ScalarExpr
    | AlterColumnDropDefault Name
    | AlterColumnSetNotNull Name
    | AlterColumnDropNotNull Name
    | AlterColumnSetDataType Name TypeName
    {-  | AlterColumnAlterIdentity
    | AlterColumnDropIdentity
    | AlterColumnDropColumnGeneration-}
    | DropColumn Name DropBehaviour
    | AddTableConstraintDef (Maybe [Name]) TableConstraint
    --  | AlterTableConstraintDef
    | DropTableConstraintDef [Name] DropBehaviour
      deriving (Eq,Show,Read,Data,Typeable)
  
  {-data ConstraintCharacteristics =
      ConstraintCharacteristics
          ConstraintCheckTime
          Deferrable
          ConstraintEnforcement
      deriving (Eq,Show,Read,Data,Typeable)
  
  data ConstraintCheckTime =
      DefaultConstraintCheckTime
    | InitiallyDeferred
    | InitiallyImmeditate
      deriving (Eq,Show,Read,Data,Typeable)
  
  data Deferrable =
      DefaultDefferable
    | Deferrable
    | NotDeferrable
      deriving (Eq,Show,Read,Data,Typeable)
  
  data ConstraintEnforcement =
      DefaultConstraintEnforcement
    | Enforced
    | NotEnforced
      deriving (Eq,Show,Read,Data,Typeable) -}
  
  {-data TableConstraintDef
      deriving (Eq,Show,Read,Data,Typeable) -}
  
  data DefaultClause =
       DefaultClause ScalarExpr
     | IdentityColumnSpec IdentityWhen [SequenceGeneratorOption]
     | GenerationClause ScalarExpr
      deriving (Eq,Show,Read,Data,Typeable)
  
  data IdentityWhen =
      GeneratedAlways
    | GeneratedByDefault
      deriving (Eq,Show,Read,Data,Typeable)
  
  data SequenceGeneratorOption =
      SGODataType TypeName
    | SGOStartWith Integer
    | SGORestart (Maybe Integer)
    | SGOIncrementBy Integer
    | SGOMaxValue Integer
    | SGONoMaxValue
    | SGOMinValue Integer
    | SGONoMinValue
    | SGOCycle
    | SGONoCycle
      deriving (Eq,Show,Read,Data,Typeable)
  
  data CheckOption =
      DefaultCheckOption
    | CascadedCheckOption
    | LocalCheckOption
      deriving (Eq,Show,Read,Data,Typeable)
  
  data AlterDomainAction =
      ADSetDefault ScalarExpr
    | ADDropDefault
    | ADAddConstraint (Maybe [Name]) ScalarExpr
    | ADDropConstraint [Name]
      deriving (Eq,Show,Read,Data,Typeable)
  
  
  data AdminOption = WithAdminOption | WithoutAdminOption
      deriving (Eq,Show,Read,Data,Typeable)
  
  data GrantOption = WithGrantOption | WithoutGrantOption
      deriving (Eq,Show,Read,Data,Typeable)
  
  data AdminOptionFor = AdminOptionFor | NoAdminOptionFor
      deriving (Eq,Show,Read,Data,Typeable)
  
  data GrantOptionFor = GrantOptionFor | NoGrantOptionFor
      deriving (Eq,Show,Read,Data,Typeable)
  
  data PrivilegeObject =
        PrivTable [Name]
      | PrivDomain [Name]
      | PrivType [Name]
      | PrivSequence [Name]
      | PrivFunction [Name]
      deriving (Eq,Show,Read,Data,Typeable)
  
  data PrivilegeAction =
        PrivAll
      | PrivSelect [Name]
      | PrivDelete
      | PrivInsert [Name]
      | PrivUpdate [Name]
      | PrivReferences [Name]
      | PrivUsage
      | PrivTrigger
      | PrivExecute
      deriving (Eq,Show,Read,Data,Typeable)
  
  -- | Comment. Useful when generating SQL code programmatically. The
  -- parser doesn't produce these.
  newtype Comment = BlockComment Text
                 deriving (Eq,Show,Read,Data,Typeable)
  
  data MakeSelect
      = MakeSelect
      {msSetQuantifier :: SetQuantifier
      ,msSelectList :: [(ScalarExpr,Maybe Name)]
      ,msFrom :: [TableRef]
      ,msWhere :: Maybe ScalarExpr
      ,msGroupBy :: [GroupingExpr]
      ,msHaving :: Maybe ScalarExpr
      ,msOrderBy :: [SortSpec]
      ,msOffset :: Maybe ScalarExpr
      ,msFetchFirst :: Maybe ScalarExpr
      }
  
  -- | Helper/'default' value for query exprs to make creating query
  -- expr values a little easier. It is defined like this:
  --
  -- > makeSelect :: MakeSelect
  -- > makeSelect
  -- >     = MakeSelect
  -- >     {msSetQuantifier = SQDefault
  -- >     ,msSelectList = []
  -- >     ,msFrom = []
  -- >     ,msWhere = Nothing
  -- >     ,msGroupBy = []
  -- >     ,msHaving = Nothing
  -- >     ,msOrderBy = []
  -- >     ,msOffset = Nothing
  -- >     ,msFetchFirst = Nothing}
  -- >
  -- > Example, to create a select query expression with a select list 'sl':
  -- >   toQueryExpr $ makeSelect {msSelectList = sl}
  
  makeSelect :: MakeSelect
  makeSelect
      = MakeSelect
      {msSetQuantifier = SQDefault
      ,msSelectList = []
      ,msFrom = []
      ,msWhere = Nothing
      ,msGroupBy = []
      ,msHaving = Nothing
      ,msOrderBy = []
      ,msOffset = Nothing
      ,msFetchFirst = Nothing}
  
  toQueryExpr :: MakeSelect -> QueryExpr
  toQueryExpr (MakeSelect q sl f w g h o ff fetch) = Select q sl f w g h o ff fetch
  