packages feed

postgresql-syntax 0.4.5.0 → 0.5.0.0

raw patch · 351 files changed

+12389/−7243 lines, 351 filesdep +QuickCheckdep +hspecdep −deepseqdep −hedgehogdep −tastydep ~rerebasePVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, hspec

Dependencies removed: deepseq, hedgehog, tasty, tasty-hunit

Dependency ranges changed: rerebase

API changes (from Hackage documentation)

- PostgresqlSyntax.Ast: AexprConstCExpr :: AexprConst -> CExpr
- PostgresqlSyntax.Ast: AliasClause :: Bool -> ColId -> Maybe NameList -> AliasClause
- PostgresqlSyntax.Ast: AliasFuncAliasClause :: AliasClause -> FuncAliasClause
- PostgresqlSyntax.Ast: AliasedExprTargetEl :: AExpr -> Ident -> TargetEl
- PostgresqlSyntax.Ast: AllIndirectionEl :: IndirectionEl
- PostgresqlSyntax.Ast: AllOpAnyOperator :: AllOp -> AnyOperator
- PostgresqlSyntax.Ast: AllQualAllOp :: AllOp -> QualAllOp
- PostgresqlSyntax.Ast: AllSelectLimitValue :: SelectLimitValue
- PostgresqlSyntax.Ast: AllSubType :: SubType
- PostgresqlSyntax.Ast: AllSubqueryOp :: AllOp -> SubqueryOp
- PostgresqlSyntax.Ast: AllTargeting :: Maybe TargetList -> Targeting
- PostgresqlSyntax.Ast: AndAExpr :: AExpr -> AExpr -> AExpr
- PostgresqlSyntax.Ast: AnyName :: ColId -> Maybe Attrs -> AnyName
- PostgresqlSyntax.Ast: AnyQualAllOp :: AnyOperator -> QualAllOp
- PostgresqlSyntax.Ast: AnySubType :: SubType
- PostgresqlSyntax.Ast: AnySubqueryOp :: AnyOperator -> SubqueryOp
- PostgresqlSyntax.Ast: ApplicationFuncExpr :: FuncApplication -> Maybe WithinGroupClause -> Maybe FilterClause -> Maybe OverClause -> FuncExpr
- PostgresqlSyntax.Ast: ApplicationFuncExprWindowless :: FuncApplication -> FuncExprWindowless
- PostgresqlSyntax.Ast: ArrayCExpr :: Either SelectWithParens ArrayExpr -> CExpr
- PostgresqlSyntax.Ast: ArrayExprListArrayExpr :: ArrayExprList -> ArrayExpr
- PostgresqlSyntax.Ast: ArrowLeftArrowRightMathOp :: MathOp
- PostgresqlSyntax.Ast: ArrowLeftMathOp :: MathOp
- PostgresqlSyntax.Ast: ArrowRightMathOp :: MathOp
- PostgresqlSyntax.Ast: ArrowUpMathOp :: MathOp
- PostgresqlSyntax.Ast: AsColIdFuncAliasClause :: ColId -> TableFuncElementList -> FuncAliasClause
- PostgresqlSyntax.Ast: AsFuncAliasClause :: TableFuncElementList -> FuncAliasClause
- PostgresqlSyntax.Ast: AscAscDesc :: AscDesc
- PostgresqlSyntax.Ast: AscDescSortBy :: AExpr -> Maybe AscDesc -> Maybe NullsOrder -> SortBy
- PostgresqlSyntax.Ast: AsteriskMathOp :: MathOp
- PostgresqlSyntax.Ast: AsteriskTargetEl :: TargetEl
- PostgresqlSyntax.Ast: AtTimeZoneAExpr :: AExpr -> AExpr -> AExpr
- PostgresqlSyntax.Ast: AttrNameIndirectionEl :: Ident -> IndirectionEl
- PostgresqlSyntax.Ast: BAexprConst :: Bconst -> AexprConst
- PostgresqlSyntax.Ast: BetweenAExprReversableOp :: Bool -> BExpr -> AExpr -> AExprReversableOp
- PostgresqlSyntax.Ast: BetweenFrameExtent :: FrameBound -> FrameBound -> FrameExtent
- PostgresqlSyntax.Ast: BetweenSymmetricAExprReversableOp :: BExpr -> AExpr -> AExprReversableOp
- PostgresqlSyntax.Ast: BigintNumeric :: Numeric
- PostgresqlSyntax.Ast: BinSimpleSelect :: SelectBinOp -> SelectClause -> Maybe Bool -> SelectClause -> SimpleSelect
- PostgresqlSyntax.Ast: Bit :: OptVarying -> Maybe ExprList -> Bit
- PostgresqlSyntax.Ast: BitSimpleTypename :: Bit -> SimpleTypename
- PostgresqlSyntax.Ast: BoolAexprConst :: Bool -> AexprConst
- PostgresqlSyntax.Ast: BooleanNumeric :: Numeric
- PostgresqlSyntax.Ast: BothTrimModifier :: TrimModifier
- PostgresqlSyntax.Ast: BoundsTypenameArrayDimensions :: ArrayBounds -> TypenameArrayDimensions
- PostgresqlSyntax.Ast: CExprAExpr :: CExpr -> AExpr
- PostgresqlSyntax.Ast: CExprBExpr :: CExpr -> BExpr
- PostgresqlSyntax.Ast: CallPreparableStmt :: CallStmt -> PreparableStmt
- PostgresqlSyntax.Ast: CallStmt :: FuncApplication -> CallStmt
- PostgresqlSyntax.Ast: CaseCExpr :: CaseExpr -> CExpr
- PostgresqlSyntax.Ast: CaseExpr :: Maybe CaseArg -> WhenClauseList -> Maybe CaseDefault -> CaseExpr
- PostgresqlSyntax.Ast: CastFuncExprCommonSubexpr :: AExpr -> Typename -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CharCharacter :: OptVarying -> Character
- PostgresqlSyntax.Ast: CharacterCharacter :: OptVarying -> Character
- PostgresqlSyntax.Ast: CharacterSimpleTypename :: Character -> SimpleTypename
- PostgresqlSyntax.Ast: CoalesceFuncExprCommonSubexpr :: ExprList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: ColIdFuncAliasClause :: ColId -> TableFuncElementList -> FuncAliasClause
- PostgresqlSyntax.Ast: ColIdOverClause :: ColId -> OverClause
- PostgresqlSyntax.Ast: CollateAExpr :: AExpr -> AnyName -> AExpr
- PostgresqlSyntax.Ast: CollationForFuncExprCommonSubexpr :: AExpr -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: ColonEqualsFuncArgExpr :: Ident -> AExpr -> FuncArgExpr
- PostgresqlSyntax.Ast: Columnref :: ColId -> Maybe Indirection -> Columnref
- PostgresqlSyntax.Ast: ColumnrefCExpr :: Columnref -> CExpr
- PostgresqlSyntax.Ast: CommonSubexprFuncExprWindowless :: FuncExprCommonSubexpr -> FuncExprWindowless
- PostgresqlSyntax.Ast: CommonTableExpr :: Ident -> Maybe (NonEmpty Ident) -> Maybe Bool -> PreparableStmt -> CommonTableExpr
- PostgresqlSyntax.Ast: ConstBitConstTypename :: ConstBit -> ConstTypename
- PostgresqlSyntax.Ast: ConstCharacter :: Character -> Maybe Int64 -> ConstCharacter
- PostgresqlSyntax.Ast: ConstCharacterConstTypename :: ConstCharacter -> ConstTypename
- PostgresqlSyntax.Ast: ConstDatetimeConstTypename :: ConstDatetime -> ConstTypename
- PostgresqlSyntax.Ast: ConstDatetimeSimpleTypename :: ConstDatetime -> SimpleTypename
- PostgresqlSyntax.Ast: ConstIntervalSimpleTypename :: Either (Maybe Interval) Iconst -> SimpleTypename
- PostgresqlSyntax.Ast: ConstTypenameAexprConst :: ConstTypename -> Sconst -> AexprConst
- PostgresqlSyntax.Ast: ConstraintConfExpr :: Name -> ConfExpr
- PostgresqlSyntax.Ast: CrossJoinMeth :: JoinMeth
- PostgresqlSyntax.Ast: CubeGroupByItem :: ExprList -> GroupByItem
- PostgresqlSyntax.Ast: CurrentCatalogFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentDateFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentRoleFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentRowFrameBound :: FrameBound
- PostgresqlSyntax.Ast: CurrentRowWindowExclusionClause :: WindowExclusionClause
- PostgresqlSyntax.Ast: CurrentSchemaFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentTimeFuncExprCommonSubexpr :: Maybe Int64 -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentTimestampFuncExprCommonSubexpr :: Maybe Int64 -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CurrentUserFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: CursorWhereOrCurrentClause :: CursorName -> WhereOrCurrentClause
- PostgresqlSyntax.Ast: DayExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: DayInterval :: Interval
- PostgresqlSyntax.Ast: DayToHourInterval :: Interval
- PostgresqlSyntax.Ast: DayToMinuteInterval :: Interval
- PostgresqlSyntax.Ast: DayToSecondInterval :: IntervalSecond -> Interval
- PostgresqlSyntax.Ast: DecNumeric :: Maybe TypeModifiers -> Numeric
- PostgresqlSyntax.Ast: DecimalNumeric :: Maybe TypeModifiers -> Numeric
- PostgresqlSyntax.Ast: DefaultAExpr :: AExpr
- PostgresqlSyntax.Ast: DefaultValuesInsertRest :: InsertRest
- PostgresqlSyntax.Ast: DeletePreparableStmt :: DeleteStmt -> PreparableStmt
- PostgresqlSyntax.Ast: DeleteStmt :: Maybe WithClause -> RelationExprOptAlias -> Maybe UsingClause -> Maybe WhereOrCurrentClause -> Maybe ReturningClause -> DeleteStmt
- PostgresqlSyntax.Ast: DescAscDesc :: AscDesc
- PostgresqlSyntax.Ast: DistinctFromAExprReversableOp :: AExpr -> AExprReversableOp
- PostgresqlSyntax.Ast: DistinctFromBExprIsOp :: BExpr -> BExprIsOp
- PostgresqlSyntax.Ast: DistinctTargeting :: Maybe ExprList -> TargetList -> Targeting
- PostgresqlSyntax.Ast: DocumentAExprReversableOp :: AExprReversableOp
- PostgresqlSyntax.Ast: DocumentBExprIsOp :: BExprIsOp
- PostgresqlSyntax.Ast: DoublePrecisionNumeric :: Numeric
- PostgresqlSyntax.Ast: EmptyArrayExpr :: ArrayExpr
- PostgresqlSyntax.Ast: EmptyGroupingSetGroupByItem :: GroupByItem
- PostgresqlSyntax.Ast: EqualsGreaterFuncArgExpr :: Ident -> AExpr -> FuncArgExpr
- PostgresqlSyntax.Ast: EqualsMathOp :: MathOp
- PostgresqlSyntax.Ast: ExceptSelectBinOp :: SelectBinOp
- PostgresqlSyntax.Ast: ExclamationEqualsMathOp :: MathOp
- PostgresqlSyntax.Ast: ExistsCExpr :: SelectWithParens -> CExpr
- PostgresqlSyntax.Ast: ExplicitRowCExpr :: ExplicitRow -> CExpr
- PostgresqlSyntax.Ast: ExplicitRowRow :: ExplicitRow -> Row
- PostgresqlSyntax.Ast: ExplicitTypenameArrayDimensions :: Maybe Iconst -> TypenameArrayDimensions
- PostgresqlSyntax.Ast: ExprFromExprListTrimList :: AExpr -> ExprList -> TrimList
- PostgresqlSyntax.Ast: ExprFuncArgExpr :: AExpr -> FuncArgExpr
- PostgresqlSyntax.Ast: ExprGroupByItem :: AExpr -> GroupByItem
- PostgresqlSyntax.Ast: ExprIndexElemDef :: AExpr -> IndexElemDef
- PostgresqlSyntax.Ast: ExprIndirectionEl :: AExpr -> IndirectionEl
- PostgresqlSyntax.Ast: ExprListArrayExpr :: ExprList -> ArrayExpr
- PostgresqlSyntax.Ast: ExprListInExpr :: ExprList -> InExpr
- PostgresqlSyntax.Ast: ExprListSubstrList :: ExprList -> SubstrList
- PostgresqlSyntax.Ast: ExprListTrimList :: ExprList -> TrimList
- PostgresqlSyntax.Ast: ExprOffsetClause :: AExpr -> OffsetClause
- PostgresqlSyntax.Ast: ExprSelectFetchFirstValue :: CExpr -> SelectFetchFirstValue
- PostgresqlSyntax.Ast: ExprSelectLimitValue :: AExpr -> SelectLimitValue
- PostgresqlSyntax.Ast: ExprSubstrList :: AExpr -> SubstrListFromFor -> SubstrList
- PostgresqlSyntax.Ast: ExprTargetEl :: AExpr -> TargetEl
- PostgresqlSyntax.Ast: ExprWhereOrCurrentClause :: AExpr -> WhereOrCurrentClause
- PostgresqlSyntax.Ast: ExtractFuncExprCommonSubexpr :: Maybe ExtractList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: ExtractList :: ExtractArg -> AExpr -> ExtractList
- PostgresqlSyntax.Ast: FAexprConst :: Fconst -> AexprConst
- PostgresqlSyntax.Ast: FalseAExprReversableOp :: AExprReversableOp
- PostgresqlSyntax.Ast: FetchFirstOffsetClause :: SelectFetchFirstValue -> Bool -> OffsetClause
- PostgresqlSyntax.Ast: FetchOnlyLimitClause :: Bool -> Maybe SelectFetchFirstValue -> Bool -> LimitClause
- PostgresqlSyntax.Ast: FirstNullsOrder :: NullsOrder
- PostgresqlSyntax.Ast: FloatNumeric :: Maybe Int64 -> Numeric
- PostgresqlSyntax.Ast: FollowingFrameBound :: AExpr -> FrameBound
- PostgresqlSyntax.Ast: ForFromSubstrListFromFor :: SubstrFor -> SubstrFrom -> SubstrListFromFor
- PostgresqlSyntax.Ast: ForLockingItem :: ForLockingStrength -> Maybe (NonEmpty QualifiedName) -> Maybe Bool -> ForLockingItem
- PostgresqlSyntax.Ast: ForSubstrListFromFor :: SubstrFor -> SubstrListFromFor
- PostgresqlSyntax.Ast: FrameClause :: FrameClauseMode -> FrameExtent -> Maybe WindowExclusionClause -> FrameClause
- PostgresqlSyntax.Ast: FromExprListTrimList :: ExprList -> TrimList
- PostgresqlSyntax.Ast: FromForSubstrListFromFor :: SubstrFrom -> SubstrFor -> SubstrListFromFor
- PostgresqlSyntax.Ast: FromSubstrListFromFor :: SubstrFrom -> SubstrListFromFor
- PostgresqlSyntax.Ast: FullJoinType :: Bool -> JoinType
- PostgresqlSyntax.Ast: FuncAexprConst :: FuncName -> Maybe FuncConstArgs -> Sconst -> AexprConst
- PostgresqlSyntax.Ast: FuncApplication :: FuncName -> Maybe FuncApplicationParams -> FuncApplication
- PostgresqlSyntax.Ast: FuncCExpr :: FuncExpr -> CExpr
- PostgresqlSyntax.Ast: FuncConstArgs :: NonEmpty FuncArgExpr -> Maybe SortClause -> FuncConstArgs
- PostgresqlSyntax.Ast: FuncExprFuncTable :: FuncExprWindowless -> OptOrdinality -> FuncTable
- PostgresqlSyntax.Ast: FuncIndexElemDef :: FuncExprWindowless -> IndexElemDef
- PostgresqlSyntax.Ast: FuncTableRef :: Bool -> FuncTable -> Maybe FuncAliasClause -> TableRef
- PostgresqlSyntax.Ast: GenericType :: TypeFunctionName -> Maybe Attrs -> Maybe TypeModifiers -> GenericType
- PostgresqlSyntax.Ast: GenericTypeSimpleTypename :: GenericType -> SimpleTypename
- PostgresqlSyntax.Ast: GlobalTempOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: GlobalTemporaryOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: GreaterEqualsMathOp :: MathOp
- PostgresqlSyntax.Ast: GreatestFuncExprCommonSubexpr :: ExprList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: GroupWindowExclusionClause :: WindowExclusionClause
- PostgresqlSyntax.Ast: GroupingCExpr :: ExprList -> CExpr
- PostgresqlSyntax.Ast: GroupingSetsGroupByItem :: NonEmpty GroupByItem -> GroupByItem
- PostgresqlSyntax.Ast: GroupsFrameClauseMode :: FrameClauseMode
- PostgresqlSyntax.Ast: HourExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: HourInterval :: Interval
- PostgresqlSyntax.Ast: HourToMinuteInterval :: Interval
- PostgresqlSyntax.Ast: HourToSecondInterval :: IntervalSecond -> Interval
- PostgresqlSyntax.Ast: IAexprConst :: Iconst -> AexprConst
- PostgresqlSyntax.Ast: IdIndexElemDef :: ColId -> IndexElemDef
- PostgresqlSyntax.Ast: IdentExtractArg :: Ident -> ExtractArg
- PostgresqlSyntax.Ast: IlikeSubqueryOp :: Bool -> SubqueryOp
- PostgresqlSyntax.Ast: IlikeVerbalExprBinOp :: VerbalExprBinOp
- PostgresqlSyntax.Ast: ImplicitRow :: ExprList -> AExpr -> ImplicitRow
- PostgresqlSyntax.Ast: ImplicitRowCExpr :: ImplicitRow -> CExpr
- PostgresqlSyntax.Ast: ImplicitRowRow :: ImplicitRow -> Row
- PostgresqlSyntax.Ast: ImplicitlyAliasedExprTargetEl :: AExpr -> Ident -> TargetEl
- PostgresqlSyntax.Ast: InAExprReversableOp :: InExpr -> AExprReversableOp
- PostgresqlSyntax.Ast: InParensCExpr :: AExpr -> Maybe Indirection -> CExpr
- PostgresqlSyntax.Ast: InParensJoinedTable :: JoinedTable -> JoinedTable
- PostgresqlSyntax.Ast: IndexElem :: IndexElemDef -> Maybe Collate -> Maybe Class -> Maybe AscDesc -> Maybe NullsOrder -> IndexElem
- PostgresqlSyntax.Ast: IndirectedFuncName :: ColId -> Indirection -> FuncName
- PostgresqlSyntax.Ast: IndirectedQualifiedName :: Ident -> Indirection -> QualifiedName
- PostgresqlSyntax.Ast: InnerJoinType :: JoinType
- PostgresqlSyntax.Ast: InsertColumnItem :: ColId -> Maybe Indirection -> InsertColumnItem
- PostgresqlSyntax.Ast: InsertPreparableStmt :: InsertStmt -> PreparableStmt
- PostgresqlSyntax.Ast: InsertStmt :: Maybe WithClause -> InsertTarget -> InsertRest -> Maybe OnConflict -> Maybe ReturningClause -> InsertStmt
- PostgresqlSyntax.Ast: InsertTarget :: QualifiedName -> Maybe ColId -> InsertTarget
- PostgresqlSyntax.Ast: IntIntervalAexprConst :: Iconst -> Sconst -> AexprConst
- PostgresqlSyntax.Ast: IntNumeric :: Numeric
- PostgresqlSyntax.Ast: IntegerNumeric :: Numeric
- PostgresqlSyntax.Ast: IntersectSelectBinOp :: SelectBinOp
- PostgresqlSyntax.Ast: IsOpBExpr :: BExpr -> Bool -> BExprIsOp -> BExpr
- PostgresqlSyntax.Ast: IsnullAExpr :: AExpr -> AExpr
- PostgresqlSyntax.Ast: ItemsForLockingClause :: NonEmpty ForLockingItem -> ForLockingClause
- PostgresqlSyntax.Ast: JoinTableRef :: JoinedTable -> Maybe AliasClause -> TableRef
- PostgresqlSyntax.Ast: KeyForLockingStrength :: ForLockingStrength
- PostgresqlSyntax.Ast: LastNullsOrder :: NullsOrder
- PostgresqlSyntax.Ast: LeadingTrimModifier :: TrimModifier
- PostgresqlSyntax.Ast: LeastFuncExprCommonSubexpr :: ExprList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: LeftJoinType :: Bool -> JoinType
- PostgresqlSyntax.Ast: LessEqualsMathOp :: MathOp
- PostgresqlSyntax.Ast: LikeSubqueryOp :: Bool -> SubqueryOp
- PostgresqlSyntax.Ast: LikeVerbalExprBinOp :: VerbalExprBinOp
- PostgresqlSyntax.Ast: LimitLimitClause :: SelectLimitValue -> Maybe AExpr -> LimitClause
- PostgresqlSyntax.Ast: LimitOffsetSelectLimit :: LimitClause -> OffsetClause -> SelectLimit
- PostgresqlSyntax.Ast: LimitSelectLimit :: LimitClause -> SelectLimit
- PostgresqlSyntax.Ast: LocalTempOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: LocalTemporaryOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: LocalTimeFuncExprCommonSubexpr :: Maybe Int64 -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: LocalTimestampFuncExprCommonSubexpr :: Maybe Int64 -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: MathAllOp :: MathOp -> AllOp
- PostgresqlSyntax.Ast: MathSymbolicExprBinOp :: MathOp -> SymbolicExprBinOp
- PostgresqlSyntax.Ast: MethJoinedTable :: JoinMeth -> TableRef -> TableRef -> JoinedTable
- PostgresqlSyntax.Ast: MinusAExpr :: AExpr -> AExpr
- PostgresqlSyntax.Ast: MinusBExpr :: BExpr -> BExpr
- PostgresqlSyntax.Ast: MinusMathOp :: MathOp
- PostgresqlSyntax.Ast: MinuteExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: MinuteInterval :: Interval
- PostgresqlSyntax.Ast: MinuteToSecondInterval :: IntervalSecond -> Interval
- PostgresqlSyntax.Ast: MonthExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: MonthInterval :: Interval
- PostgresqlSyntax.Ast: NationalCharCharacter :: OptVarying -> Character
- PostgresqlSyntax.Ast: NationalCharacterCharacter :: OptVarying -> Character
- PostgresqlSyntax.Ast: NaturalJoinMeth :: Maybe JoinType -> JoinMeth
- PostgresqlSyntax.Ast: NcharCharacter :: OptVarying -> Character
- PostgresqlSyntax.Ast: NoKeyUpdateForLockingStrength :: ForLockingStrength
- PostgresqlSyntax.Ast: NoOthersWindowExclusionClause :: WindowExclusionClause
- PostgresqlSyntax.Ast: NoParensSelectWithParens :: SelectNoParens -> SelectWithParens
- PostgresqlSyntax.Ast: NormalFuncApplicationParams :: Maybe Bool -> NonEmpty FuncArgExpr -> Maybe SortClause -> FuncApplicationParams
- PostgresqlSyntax.Ast: NormalSimpleSelect :: Maybe Targeting -> Maybe IntoClause -> Maybe FromClause -> Maybe WhereClause -> Maybe GroupClause -> Maybe HavingClause -> Maybe WindowClause -> SimpleSelect
- PostgresqlSyntax.Ast: NormalTargeting :: TargetList -> Targeting
- PostgresqlSyntax.Ast: NotAExpr :: AExpr -> AExpr
- PostgresqlSyntax.Ast: NothingOnConflictDo :: OnConflictDo
- PostgresqlSyntax.Ast: NotnullAExpr :: AExpr -> AExpr
- PostgresqlSyntax.Ast: NullAExprReversableOp :: AExprReversableOp
- PostgresqlSyntax.Ast: NullAexprConst :: AexprConst
- PostgresqlSyntax.Ast: NullIfFuncExprCommonSubexpr :: AExpr -> AExpr -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: NumSelectFetchFirstValue :: Bool -> Either Int64 Double -> SelectFetchFirstValue
- PostgresqlSyntax.Ast: NumericConstTypename :: Numeric -> ConstTypename
- PostgresqlSyntax.Ast: NumericNumeric :: Maybe TypeModifiers -> Numeric
- PostgresqlSyntax.Ast: NumericSimpleTypename :: Numeric -> SimpleTypename
- PostgresqlSyntax.Ast: OfAExprReversableOp :: TypeList -> AExprReversableOp
- PostgresqlSyntax.Ast: OfBExprIsOp :: TypeList -> BExprIsOp
- PostgresqlSyntax.Ast: OffsetLimitSelectLimit :: OffsetClause -> LimitClause -> SelectLimit
- PostgresqlSyntax.Ast: OffsetSelectLimit :: OffsetClause -> SelectLimit
- PostgresqlSyntax.Ast: OnConflict :: Maybe ConfExpr -> OnConflictDo -> OnConflict
- PostgresqlSyntax.Ast: OnJoinQual :: AExpr -> JoinQual
- PostgresqlSyntax.Ast: OnlyRelationExpr :: QualifiedName -> Bool -> RelationExpr
- PostgresqlSyntax.Ast: OpAllOp :: Op -> AllOp
- PostgresqlSyntax.Ast: OpQualOp :: Op -> QualOp
- PostgresqlSyntax.Ast: OperatorQualOp :: AnyOperator -> QualOp
- PostgresqlSyntax.Ast: OrAExpr :: AExpr -> AExpr -> AExpr
- PostgresqlSyntax.Ast: OverlapsAExpr :: Row -> Row -> AExpr
- PostgresqlSyntax.Ast: OverlayFuncExprCommonSubexpr :: OverlayList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: OverlayList :: AExpr -> OverlayPlacing -> SubstrFrom -> Maybe SubstrFor -> OverlayList
- PostgresqlSyntax.Ast: ParamCExpr :: Int -> Maybe Indirection -> CExpr
- PostgresqlSyntax.Ast: PercentMathOp :: MathOp
- PostgresqlSyntax.Ast: PlusAExpr :: AExpr -> AExpr
- PostgresqlSyntax.Ast: PlusBExpr :: BExpr -> BExpr
- PostgresqlSyntax.Ast: PlusMathOp :: MathOp
- PostgresqlSyntax.Ast: PositionFuncExprCommonSubexpr :: Maybe PositionList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: PositionList :: BExpr -> BExpr -> PositionList
- PostgresqlSyntax.Ast: PrecedingFrameBound :: AExpr -> FrameBound
- PostgresqlSyntax.Ast: PrefixQualOpAExpr :: QualOp -> AExpr -> AExpr
- PostgresqlSyntax.Ast: QualJoinMeth :: Maybe JoinType -> JoinQual -> JoinMeth
- PostgresqlSyntax.Ast: QualOpBExpr :: QualOp -> BExpr -> BExpr
- PostgresqlSyntax.Ast: QualSymbolicExprBinOp :: QualOp -> SymbolicExprBinOp
- PostgresqlSyntax.Ast: QualifedOptTempTableName :: QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: QualifiedAnyOperator :: ColId -> AnyOperator -> AnyOperator
- PostgresqlSyntax.Ast: QuotedIdent :: Text -> Ident
- PostgresqlSyntax.Ast: RangeFrameClauseMode :: FrameClauseMode
- PostgresqlSyntax.Ast: ReadOnlyForLockingClause :: ForLockingClause
- PostgresqlSyntax.Ast: RealNumeric :: Numeric
- PostgresqlSyntax.Ast: RelationExprOptAlias :: RelationExpr -> Maybe (Bool, ColId) -> RelationExprOptAlias
- PostgresqlSyntax.Ast: RelationExprTableRef :: RelationExpr -> Maybe AliasClause -> Maybe TablesampleClause -> TableRef
- PostgresqlSyntax.Ast: ReversableOpAExpr :: AExpr -> Bool -> AExprReversableOp -> AExpr
- PostgresqlSyntax.Ast: RightJoinType :: Bool -> JoinType
- PostgresqlSyntax.Ast: RollupGroupByItem :: ExprList -> GroupByItem
- PostgresqlSyntax.Ast: RowsFrameClauseMode :: FrameClauseMode
- PostgresqlSyntax.Ast: RowsFromFuncTable :: RowsfromList -> OptOrdinality -> FuncTable
- PostgresqlSyntax.Ast: RowsfromItem :: FuncExprWindowless -> Maybe ColDefList -> RowsfromItem
- PostgresqlSyntax.Ast: SAexprConst :: Sconst -> AexprConst
- PostgresqlSyntax.Ast: SconstExtractArg :: Sconst -> ExtractArg
- PostgresqlSyntax.Ast: SecondExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: SecondInterval :: IntervalSecond -> Interval
- PostgresqlSyntax.Ast: SelectInExpr :: SelectWithParens -> InExpr
- PostgresqlSyntax.Ast: SelectInsertRest :: Maybe InsertColumnList -> Maybe OverrideKind -> SelectStmt -> InsertRest
- PostgresqlSyntax.Ast: SelectNoParens :: Maybe WithClause -> SelectClause -> Maybe SortClause -> Maybe SelectLimit -> Maybe ForLockingClause -> SelectNoParens
- PostgresqlSyntax.Ast: SelectPreparableStmt :: SelectStmt -> PreparableStmt
- PostgresqlSyntax.Ast: SelectTableRef :: Bool -> SelectWithParens -> Maybe AliasClause -> TableRef
- PostgresqlSyntax.Ast: SelectWithParensCExpr :: SelectWithParens -> Maybe Indirection -> CExpr
- PostgresqlSyntax.Ast: SessionUserFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: SetTarget :: ColId -> Maybe Indirection -> SetTarget
- PostgresqlSyntax.Ast: ShareForLockingStrength :: ForLockingStrength
- PostgresqlSyntax.Ast: SimilarToVerbalExprBinOp :: VerbalExprBinOp
- PostgresqlSyntax.Ast: SimpleQualifiedName :: Ident -> QualifiedName
- PostgresqlSyntax.Ast: SimpleRelationExpr :: QualifiedName -> Bool -> RelationExpr
- PostgresqlSyntax.Ast: SingularFrameExtent :: FrameBound -> FrameExtent
- PostgresqlSyntax.Ast: SlashMathOp :: MathOp
- PostgresqlSyntax.Ast: SliceIndirectionEl :: Maybe AExpr -> Maybe AExpr -> IndirectionEl
- PostgresqlSyntax.Ast: SmallintNumeric :: Numeric
- PostgresqlSyntax.Ast: SomeSubType :: SubType
- PostgresqlSyntax.Ast: StarFuncApplicationParams :: FuncApplicationParams
- PostgresqlSyntax.Ast: StringIntervalAexprConst :: Sconst -> Maybe Interval -> AexprConst
- PostgresqlSyntax.Ast: SubexprFuncExpr :: FuncExprCommonSubexpr -> FuncExpr
- PostgresqlSyntax.Ast: SubqueryAExpr :: AExpr -> SubqueryOp -> SubType -> Either SelectWithParens AExpr -> AExpr
- PostgresqlSyntax.Ast: SubstringFuncExprCommonSubexpr :: Maybe SubstrList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: SuffixQualOpAExpr :: AExpr -> QualOp -> AExpr
- PostgresqlSyntax.Ast: SymbolicBinOpAExpr :: AExpr -> SymbolicExprBinOp -> AExpr -> AExpr
- PostgresqlSyntax.Ast: SymbolicBinOpBExpr :: BExpr -> SymbolicExprBinOp -> BExpr -> BExpr
- PostgresqlSyntax.Ast: SystemOverrideKind :: OverrideKind
- PostgresqlSyntax.Ast: TableFuncElement :: ColId -> Typename -> Maybe CollateClause -> TableFuncElement
- PostgresqlSyntax.Ast: TableOptTempTableName :: QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: TableSimpleSelect :: RelationExpr -> SimpleSelect
- PostgresqlSyntax.Ast: TablesampleClause :: FuncName -> ExprList -> Maybe RepeatableClause -> TablesampleClause
- PostgresqlSyntax.Ast: TargetListSetClause :: SetTargetList -> AExpr -> SetClause
- PostgresqlSyntax.Ast: TargetSetClause :: SetTarget -> AExpr -> SetClause
- PostgresqlSyntax.Ast: TempOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: TemporaryOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: TiesWindowExclusionClause :: WindowExclusionClause
- PostgresqlSyntax.Ast: TimeConstDatetime :: Maybe Int64 -> Maybe Timezone -> ConstDatetime
- PostgresqlSyntax.Ast: TimestampConstDatetime :: Maybe Int64 -> Maybe Timezone -> ConstDatetime
- PostgresqlSyntax.Ast: TrailingTrimModifier :: TrimModifier
- PostgresqlSyntax.Ast: TreatFuncExprCommonSubexpr :: AExpr -> Typename -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: TrimFuncExprCommonSubexpr :: Maybe TrimModifier -> TrimList -> FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: TrueAExprReversableOp :: AExprReversableOp
- PostgresqlSyntax.Ast: TypeFuncName :: TypeFunctionName -> FuncName
- PostgresqlSyntax.Ast: TypecastAExpr :: AExpr -> Typename -> AExpr
- PostgresqlSyntax.Ast: TypecastBExpr :: BExpr -> Typename -> BExpr
- PostgresqlSyntax.Ast: Typename :: Bool -> SimpleTypename -> Bool -> Maybe (TypenameArrayDimensions, Bool) -> Typename
- PostgresqlSyntax.Ast: UnboundedFollowingFrameBound :: FrameBound
- PostgresqlSyntax.Ast: UnboundedPrecedingFrameBound :: FrameBound
- PostgresqlSyntax.Ast: UnionSelectBinOp :: SelectBinOp
- PostgresqlSyntax.Ast: UniqueAExpr :: SelectWithParens -> AExpr
- PostgresqlSyntax.Ast: UnknownAExprReversableOp :: AExprReversableOp
- PostgresqlSyntax.Ast: UnloggedOptTempTableName :: Bool -> QualifiedName -> OptTempTableName
- PostgresqlSyntax.Ast: UnquotedIdent :: Text -> Ident
- PostgresqlSyntax.Ast: UpdateForLockingStrength :: ForLockingStrength
- PostgresqlSyntax.Ast: UpdateOnConflictDo :: SetClauseList -> Maybe WhereClause -> OnConflictDo
- PostgresqlSyntax.Ast: UpdatePreparableStmt :: UpdateStmt -> PreparableStmt
- PostgresqlSyntax.Ast: UpdateStmt :: Maybe WithClause -> RelationExprOptAlias -> SetClauseList -> Maybe FromClause -> Maybe WhereOrCurrentClause -> Maybe ReturningClause -> UpdateStmt
- PostgresqlSyntax.Ast: UserFuncExprCommonSubexpr :: FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: UserOverrideKind :: OverrideKind
- PostgresqlSyntax.Ast: UsingJoinQual :: NonEmpty Ident -> JoinQual
- PostgresqlSyntax.Ast: UsingSortBy :: AExpr -> QualAllOp -> Maybe NullsOrder -> SortBy
- PostgresqlSyntax.Ast: ValuesSimpleSelect :: ValuesClause -> SimpleSelect
- PostgresqlSyntax.Ast: VarcharCharacter :: Character
- PostgresqlSyntax.Ast: VariadicFuncApplicationParams :: Maybe (NonEmpty FuncArgExpr) -> FuncArgExpr -> Maybe SortClause -> FuncApplicationParams
- PostgresqlSyntax.Ast: VerbalExprBinOpAExpr :: AExpr -> Bool -> VerbalExprBinOp -> AExpr -> Maybe AExpr -> AExpr
- PostgresqlSyntax.Ast: WhenClause :: AExpr -> AExpr -> WhenClause
- PostgresqlSyntax.Ast: WhereConfExpr :: IndexParams -> Maybe WhereClause -> ConfExpr
- PostgresqlSyntax.Ast: WindowDefinition :: Ident -> WindowSpecification -> WindowDefinition
- PostgresqlSyntax.Ast: WindowOverClause :: WindowSpecification -> OverClause
- PostgresqlSyntax.Ast: WindowSpecification :: Maybe ExistingWindowName -> Maybe PartitionClause -> Maybe SortClause -> Maybe FrameClause -> WindowSpecification
- PostgresqlSyntax.Ast: WithClause :: Bool -> NonEmpty CommonTableExpr -> WithClause
- PostgresqlSyntax.Ast: WithParensSelectWithParens :: SelectWithParens -> SelectWithParens
- PostgresqlSyntax.Ast: XAexprConst :: Xconst -> AexprConst
- PostgresqlSyntax.Ast: YearExtractArg :: ExtractArg
- PostgresqlSyntax.Ast: YearInterval :: Interval
- PostgresqlSyntax.Ast: YearToMonthInterval :: Interval
- PostgresqlSyntax.Ast: data AExpr
- PostgresqlSyntax.Ast: data AExprReversableOp
- PostgresqlSyntax.Ast: data AexprConst
- PostgresqlSyntax.Ast: data AliasClause
- PostgresqlSyntax.Ast: data AllOp
- PostgresqlSyntax.Ast: data AnyName
- PostgresqlSyntax.Ast: data AnyOperator
- PostgresqlSyntax.Ast: data ArrayExpr
- PostgresqlSyntax.Ast: data AscDesc
- PostgresqlSyntax.Ast: data BExpr
- PostgresqlSyntax.Ast: data BExprIsOp
- PostgresqlSyntax.Ast: data Bit
- PostgresqlSyntax.Ast: data CExpr
- PostgresqlSyntax.Ast: data CaseExpr
- PostgresqlSyntax.Ast: data Character
- PostgresqlSyntax.Ast: data Columnref
- PostgresqlSyntax.Ast: data CommonTableExpr
- PostgresqlSyntax.Ast: data ConfExpr
- PostgresqlSyntax.Ast: data ConstCharacter
- PostgresqlSyntax.Ast: data ConstDatetime
- PostgresqlSyntax.Ast: data ConstTypename
- PostgresqlSyntax.Ast: data DeleteStmt
- PostgresqlSyntax.Ast: data ExtractArg
- PostgresqlSyntax.Ast: data ExtractList
- PostgresqlSyntax.Ast: data ForLockingClause
- PostgresqlSyntax.Ast: data ForLockingItem
- PostgresqlSyntax.Ast: data ForLockingStrength
- PostgresqlSyntax.Ast: data FrameBound
- PostgresqlSyntax.Ast: data FrameClause
- PostgresqlSyntax.Ast: data FrameClauseMode
- PostgresqlSyntax.Ast: data FrameExtent
- PostgresqlSyntax.Ast: data FuncAliasClause
- PostgresqlSyntax.Ast: data FuncApplication
- PostgresqlSyntax.Ast: data FuncApplicationParams
- PostgresqlSyntax.Ast: data FuncArgExpr
- PostgresqlSyntax.Ast: data FuncConstArgs
- PostgresqlSyntax.Ast: data FuncExpr
- PostgresqlSyntax.Ast: data FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: data FuncExprWindowless
- PostgresqlSyntax.Ast: data FuncName
- PostgresqlSyntax.Ast: data FuncTable
- PostgresqlSyntax.Ast: data GenericType
- PostgresqlSyntax.Ast: data GroupByItem
- PostgresqlSyntax.Ast: data Ident
- PostgresqlSyntax.Ast: data ImplicitRow
- PostgresqlSyntax.Ast: data InExpr
- PostgresqlSyntax.Ast: data IndexElem
- PostgresqlSyntax.Ast: data IndexElemDef
- PostgresqlSyntax.Ast: data IndirectionEl
- PostgresqlSyntax.Ast: data InsertColumnItem
- PostgresqlSyntax.Ast: data InsertRest
- PostgresqlSyntax.Ast: data InsertStmt
- PostgresqlSyntax.Ast: data InsertTarget
- PostgresqlSyntax.Ast: data Interval
- PostgresqlSyntax.Ast: data JoinMeth
- PostgresqlSyntax.Ast: data JoinQual
- PostgresqlSyntax.Ast: data JoinType
- PostgresqlSyntax.Ast: data JoinedTable
- PostgresqlSyntax.Ast: data LimitClause
- PostgresqlSyntax.Ast: data MathOp
- PostgresqlSyntax.Ast: data NullsOrder
- PostgresqlSyntax.Ast: data Numeric
- PostgresqlSyntax.Ast: data OffsetClause
- PostgresqlSyntax.Ast: data OnConflict
- PostgresqlSyntax.Ast: data OnConflictDo
- PostgresqlSyntax.Ast: data OptTempTableName
- PostgresqlSyntax.Ast: data OverClause
- PostgresqlSyntax.Ast: data OverlayList
- PostgresqlSyntax.Ast: data OverrideKind
- PostgresqlSyntax.Ast: data PositionList
- PostgresqlSyntax.Ast: data PreparableStmt
- PostgresqlSyntax.Ast: data QualAllOp
- PostgresqlSyntax.Ast: data QualOp
- PostgresqlSyntax.Ast: data QualifiedName
- PostgresqlSyntax.Ast: data RelationExpr
- PostgresqlSyntax.Ast: data RelationExprOptAlias
- PostgresqlSyntax.Ast: data Row
- PostgresqlSyntax.Ast: data RowsfromItem
- PostgresqlSyntax.Ast: data SelectBinOp
- PostgresqlSyntax.Ast: data SelectFetchFirstValue
- PostgresqlSyntax.Ast: data SelectLimit
- PostgresqlSyntax.Ast: data SelectLimitValue
- PostgresqlSyntax.Ast: data SelectNoParens
- PostgresqlSyntax.Ast: data SelectWithParens
- PostgresqlSyntax.Ast: data SetClause
- PostgresqlSyntax.Ast: data SetTarget
- PostgresqlSyntax.Ast: data SimpleSelect
- PostgresqlSyntax.Ast: data SimpleTypename
- PostgresqlSyntax.Ast: data SortBy
- PostgresqlSyntax.Ast: data SubType
- PostgresqlSyntax.Ast: data SubqueryOp
- PostgresqlSyntax.Ast: data SubstrList
- PostgresqlSyntax.Ast: data SubstrListFromFor
- PostgresqlSyntax.Ast: data SymbolicExprBinOp
- PostgresqlSyntax.Ast: data TableFuncElement
- PostgresqlSyntax.Ast: data TableRef
- PostgresqlSyntax.Ast: data TablesampleClause
- PostgresqlSyntax.Ast: data TargetEl
- PostgresqlSyntax.Ast: data Targeting
- PostgresqlSyntax.Ast: data TrimList
- PostgresqlSyntax.Ast: data TrimModifier
- PostgresqlSyntax.Ast: data Typename
- PostgresqlSyntax.Ast: data TypenameArrayDimensions
- PostgresqlSyntax.Ast: data UpdateStmt
- PostgresqlSyntax.Ast: data VerbalExprBinOp
- PostgresqlSyntax.Ast: data WhenClause
- PostgresqlSyntax.Ast: data WhereOrCurrentClause
- PostgresqlSyntax.Ast: data WindowDefinition
- PostgresqlSyntax.Ast: data WindowExclusionClause
- PostgresqlSyntax.Ast: data WindowSpecification
- PostgresqlSyntax.Ast: data WithClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AExprReversableOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AexprConst
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AliasClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AllOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AnyName
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AnyOperator
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ArrayExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.BExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.BExprIsOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Bit
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.CExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.CallStmt
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.CaseExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Character
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Columnref
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.CommonTableExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ConfExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ConstCharacter
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ConstDatetime
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ConstTypename
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.DeleteStmt
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ExtractArg
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ExtractList
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ForLockingClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ForLockingItem
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ForLockingStrength
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FrameBound
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FrameClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FrameClauseMode
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FrameExtent
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncAliasClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncApplication
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncApplicationParams
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncArgExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncConstArgs
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncExprWindowless
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncName
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.FuncTable
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.GenericType
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.GroupByItem
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Ident
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.ImplicitRow
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.InExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.IndexElem
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.IndexElemDef
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.IndirectionEl
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.InsertColumnItem
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.InsertRest
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.InsertStmt
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.InsertTarget
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Interval
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.JoinMeth
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.JoinQual
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.JoinType
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.JoinedTable
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.LimitClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Numeric
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OffsetClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OnConflict
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OnConflictDo
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OptTempTableName
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OverClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OverlayList
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.PositionList
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.PreparableStmt
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.QualAllOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.QualOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.QualifiedName
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.RelationExpr
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.RelationExprOptAlias
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Row
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.RowsfromItem
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectBinOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectFetchFirstValue
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectLimit
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectLimitValue
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectNoParens
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SelectWithParens
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SetClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SetTarget
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SimpleSelect
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SimpleTypename
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SortBy
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SubqueryOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SubstrList
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SubstrListFromFor
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.SymbolicExprBinOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TableFuncElement
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TableRef
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TablesampleClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TargetEl
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Targeting
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TrimList
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.Typename
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.TypenameArrayDimensions
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.UpdateStmt
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WhenClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WhereOrCurrentClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WindowDefinition
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WindowExclusionClause
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WindowSpecification
- PostgresqlSyntax.Ast: instance Data.Data.Data PostgresqlSyntax.Ast.WithClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AExprReversableOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AexprConst
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AliasClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AllOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AnyName
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AnyOperator
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ArrayExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.BExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.BExprIsOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Bit
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.CExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.CallStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.CaseExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Character
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Columnref
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.CommonTableExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ConfExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ConstCharacter
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ConstDatetime
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ConstTypename
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.DeleteStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ExtractArg
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ExtractList
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ForLockingClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ForLockingItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ForLockingStrength
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FrameBound
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FrameClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FrameClauseMode
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FrameExtent
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncAliasClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncApplication
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncApplicationParams
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncArgExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncConstArgs
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncExprWindowless
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncName
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.FuncTable
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.GenericType
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.GroupByItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Ident
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.ImplicitRow
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.InExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.IndexElem
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.IndexElemDef
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.IndirectionEl
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.InsertColumnItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.InsertRest
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.InsertStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.InsertTarget
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Interval
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.JoinMeth
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.JoinQual
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.JoinType
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.JoinedTable
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.LimitClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Numeric
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OffsetClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OnConflict
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OnConflictDo
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OptTempTableName
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OverClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OverlayList
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.PositionList
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.PreparableStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.QualAllOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.QualOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.QualifiedName
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.RelationExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.RelationExprOptAlias
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Row
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.RowsfromItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectFetchFirstValue
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectLimit
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectLimitValue
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectNoParens
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SelectWithParens
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SetClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SetTarget
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SimpleSelect
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SimpleTypename
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SortBy
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SubqueryOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SubstrList
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SubstrListFromFor
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.SymbolicExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TableFuncElement
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TableRef
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TablesampleClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TargetEl
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Targeting
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TrimList
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.Typename
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.TypenameArrayDimensions
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.UpdateStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WhenClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WhereOrCurrentClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WindowDefinition
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WindowExclusionClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WindowSpecification
- PostgresqlSyntax.Ast: instance GHC.Classes.Eq PostgresqlSyntax.Ast.WithClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AExprReversableOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AexprConst
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AliasClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AllOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AnyName
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AnyOperator
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ArrayExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.BExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.BExprIsOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Bit
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.CExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.CallStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.CaseExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Character
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Columnref
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.CommonTableExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ConfExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ConstCharacter
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ConstDatetime
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ConstTypename
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.DeleteStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ExtractArg
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ExtractList
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ForLockingClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ForLockingItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ForLockingStrength
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FrameBound
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FrameClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FrameClauseMode
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FrameExtent
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncAliasClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncApplication
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncApplicationParams
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncArgExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncConstArgs
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncExprWindowless
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncName
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.FuncTable
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.GenericType
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.GroupByItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Ident
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.ImplicitRow
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.InExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.IndexElem
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.IndexElemDef
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.IndirectionEl
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.InsertColumnItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.InsertRest
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.InsertStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.InsertTarget
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Interval
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.JoinMeth
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.JoinQual
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.JoinType
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.JoinedTable
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.LimitClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Numeric
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OffsetClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OnConflict
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OnConflictDo
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OptTempTableName
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OverClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OverlayList
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.PositionList
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.PreparableStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.QualAllOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.QualOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.QualifiedName
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.RelationExpr
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.RelationExprOptAlias
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Row
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.RowsfromItem
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectFetchFirstValue
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectLimit
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectLimitValue
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectNoParens
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SelectWithParens
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SetClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SetTarget
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SimpleSelect
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SimpleTypename
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SortBy
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SubqueryOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SubstrList
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SubstrListFromFor
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.SymbolicExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TableFuncElement
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TableRef
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TablesampleClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TargetEl
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Targeting
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TrimList
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.Typename
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.TypenameArrayDimensions
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.UpdateStmt
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WhenClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WhereOrCurrentClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WindowDefinition
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WindowExclusionClause
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WindowSpecification
- PostgresqlSyntax.Ast: instance GHC.Classes.Ord PostgresqlSyntax.Ast.WithClause
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Enum.Bounded PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Enum.Enum PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AExprReversableOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AexprConst
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AliasClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AllOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AnyName
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AnyOperator
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ArrayExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.BExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.BExprIsOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Bit
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.CExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.CallStmt
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.CaseExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Character
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Columnref
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.CommonTableExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ConfExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ConstCharacter
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ConstDatetime
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ConstTypename
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.DeleteStmt
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ExtractArg
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ExtractList
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ForLockingClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ForLockingItem
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ForLockingStrength
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FrameBound
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FrameClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FrameClauseMode
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FrameExtent
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncAliasClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncApplication
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncApplicationParams
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncArgExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncConstArgs
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncExprWindowless
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncName
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.FuncTable
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.GenericType
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.GroupByItem
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Ident
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.ImplicitRow
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.InExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.IndexElem
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.IndexElemDef
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.IndirectionEl
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.InsertColumnItem
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.InsertRest
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.InsertStmt
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.InsertTarget
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Interval
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.JoinMeth
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.JoinQual
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.JoinType
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.JoinedTable
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.LimitClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Numeric
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OffsetClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OnConflict
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OnConflictDo
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OptTempTableName
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OverClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OverlayList
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.PositionList
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.PreparableStmt
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.QualAllOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.QualOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.QualifiedName
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.RelationExpr
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.RelationExprOptAlias
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Row
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.RowsfromItem
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectBinOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectFetchFirstValue
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectLimit
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectLimitValue
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectNoParens
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SelectWithParens
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SetClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SetTarget
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SimpleSelect
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SimpleTypename
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SortBy
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SubqueryOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SubstrList
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SubstrListFromFor
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.SymbolicExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TableFuncElement
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TableRef
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TablesampleClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TargetEl
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Targeting
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TrimList
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.Typename
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.TypenameArrayDimensions
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.UpdateStmt
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WhenClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WhereOrCurrentClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WindowDefinition
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WindowExclusionClause
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WindowSpecification
- PostgresqlSyntax.Ast: instance GHC.Generics.Generic PostgresqlSyntax.Ast.WithClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AExprReversableOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AexprConst
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AliasClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AllOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AnyName
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AnyOperator
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ArrayExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.AscDesc
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.BExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.BExprIsOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Bit
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.CExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.CallStmt
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.CaseExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Character
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Columnref
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.CommonTableExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ConfExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ConstCharacter
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ConstDatetime
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ConstTypename
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.DeleteStmt
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ExtractArg
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ExtractList
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ForLockingClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ForLockingItem
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ForLockingStrength
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FrameBound
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FrameClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FrameClauseMode
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FrameExtent
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncAliasClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncApplication
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncApplicationParams
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncArgExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncConstArgs
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncExprCommonSubexpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncExprWindowless
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncName
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.FuncTable
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.GenericType
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.GroupByItem
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Ident
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.ImplicitRow
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.InExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.IndexElem
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.IndexElemDef
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.IndirectionEl
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.InsertColumnItem
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.InsertRest
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.InsertStmt
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.InsertTarget
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Interval
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.JoinMeth
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.JoinQual
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.JoinType
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.JoinedTable
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.LimitClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.MathOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.NullsOrder
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Numeric
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OffsetClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OnConflict
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OnConflictDo
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OptTempTableName
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OverClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OverlayList
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.OverrideKind
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.PositionList
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.PreparableStmt
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.QualAllOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.QualOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.QualifiedName
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.RelationExpr
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.RelationExprOptAlias
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Row
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.RowsfromItem
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectBinOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectFetchFirstValue
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectLimit
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectLimitValue
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectNoParens
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SelectWithParens
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SetClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SetTarget
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SimpleSelect
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SimpleTypename
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SortBy
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SubType
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SubqueryOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SubstrList
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SubstrListFromFor
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.SymbolicExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TableFuncElement
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TableRef
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TablesampleClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TargetEl
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Targeting
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TrimList
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TrimModifier
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.Typename
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.TypenameArrayDimensions
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.UpdateStmt
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.VerbalExprBinOp
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WhenClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WhereOrCurrentClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WindowDefinition
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WindowExclusionClause
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WindowSpecification
- PostgresqlSyntax.Ast: instance GHC.Show.Show PostgresqlSyntax.Ast.WithClause
- PostgresqlSyntax.Ast: newtype CallStmt
- PostgresqlSyntax.Ast: type ArrayBounds = NonEmpty Maybe Iconst
- PostgresqlSyntax.Ast: type ArrayExprList = NonEmpty ArrayExpr
- PostgresqlSyntax.Ast: type AttrName = ColLabel
- PostgresqlSyntax.Ast: type Attrs = NonEmpty AttrName
- PostgresqlSyntax.Ast: type Bconst = Text
- PostgresqlSyntax.Ast: type CaseArg = AExpr
- PostgresqlSyntax.Ast: type CaseDefault = AExpr
- PostgresqlSyntax.Ast: type Class = AnyName
- PostgresqlSyntax.Ast: type ColDefList = TableFuncElementList
- PostgresqlSyntax.Ast: type ColId = Ident
- PostgresqlSyntax.Ast: type ColLabel = Ident
- PostgresqlSyntax.Ast: type Collate = AnyName
- PostgresqlSyntax.Ast: type CollateClause = AnyName
- PostgresqlSyntax.Ast: type ConstBit = Bit
- PostgresqlSyntax.Ast: type CursorName = Name
- PostgresqlSyntax.Ast: type ExistingWindowName = ColId
- PostgresqlSyntax.Ast: type ExplicitRow = Maybe ExprList
- PostgresqlSyntax.Ast: type ExprList = NonEmpty AExpr
- PostgresqlSyntax.Ast: type Fconst = Double
- PostgresqlSyntax.Ast: type FilterClause = AExpr
- PostgresqlSyntax.Ast: type FromClause = NonEmpty TableRef
- PostgresqlSyntax.Ast: type FromList = NonEmpty TableRef
- PostgresqlSyntax.Ast: type GroupClause = NonEmpty GroupByItem
- PostgresqlSyntax.Ast: type HavingClause = AExpr
- PostgresqlSyntax.Ast: type Iconst = Int64
- PostgresqlSyntax.Ast: type IndexParams = NonEmpty IndexElem
- PostgresqlSyntax.Ast: type Indirection = NonEmpty IndirectionEl
- PostgresqlSyntax.Ast: type InsertColumnList = NonEmpty InsertColumnItem
- PostgresqlSyntax.Ast: type IntervalSecond = Maybe Int64
- PostgresqlSyntax.Ast: type IntoClause = OptTempTableName
- PostgresqlSyntax.Ast: type Name = ColId
- PostgresqlSyntax.Ast: type NameList = NonEmpty Name
- PostgresqlSyntax.Ast: type Op = Text
- PostgresqlSyntax.Ast: type OptOrdinality = Bool
- PostgresqlSyntax.Ast: type OptVarying = Bool
- PostgresqlSyntax.Ast: type OverlayPlacing = AExpr
- PostgresqlSyntax.Ast: type PartitionClause = ExprList
- PostgresqlSyntax.Ast: type RepeatableClause = AExpr
- PostgresqlSyntax.Ast: type ReturningClause = TargetList
- PostgresqlSyntax.Ast: type RowsfromList = NonEmpty RowsfromItem
- PostgresqlSyntax.Ast: type Sconst = Text
- PostgresqlSyntax.Ast: type SelectClause = Either SimpleSelect SelectWithParens
- PostgresqlSyntax.Ast: type SelectStmt = Either SelectNoParens SelectWithParens
- PostgresqlSyntax.Ast: type SetClauseList = NonEmpty SetClause
- PostgresqlSyntax.Ast: type SetTargetList = NonEmpty SetTarget
- PostgresqlSyntax.Ast: type SortClause = NonEmpty SortBy
- PostgresqlSyntax.Ast: type SubstrFor = AExpr
- PostgresqlSyntax.Ast: type SubstrFrom = AExpr
- PostgresqlSyntax.Ast: type TableFuncElementList = NonEmpty TableFuncElement
- PostgresqlSyntax.Ast: type TargetList = NonEmpty TargetEl
- PostgresqlSyntax.Ast: type Timezone = Bool
- PostgresqlSyntax.Ast: type TypeFunctionName = Ident
- PostgresqlSyntax.Ast: type TypeList = NonEmpty Typename
- PostgresqlSyntax.Ast: type TypeModifiers = ExprList
- PostgresqlSyntax.Ast: type UsingClause = FromList
- PostgresqlSyntax.Ast: type ValuesClause = NonEmpty ExprList
- PostgresqlSyntax.Ast: type WhenClauseList = NonEmpty WhenClause
- PostgresqlSyntax.Ast: type WhereClause = AExpr
- PostgresqlSyntax.Ast: type WindowClause = NonEmpty WindowDefinition
- PostgresqlSyntax.Ast: type WithinGroupClause = SortClause
- PostgresqlSyntax.Ast: type Xconst = Text
- PostgresqlSyntax.KeywordSet: colId :: HashSet Text
- PostgresqlSyntax.KeywordSet: colNameKeyword :: HashSet Text
- PostgresqlSyntax.KeywordSet: keyword :: HashSet Text
- PostgresqlSyntax.KeywordSet: lexicalBinOp :: HashSet Text
- PostgresqlSyntax.KeywordSet: mathOp :: HashSet Text
- PostgresqlSyntax.KeywordSet: nonOp :: HashSet Text
- PostgresqlSyntax.KeywordSet: reservedKeyword :: HashSet Text
- PostgresqlSyntax.KeywordSet: symbolicBinOp :: HashSet Text
- PostgresqlSyntax.KeywordSet: typeFuncNameKeyword :: HashSet Text
- PostgresqlSyntax.KeywordSet: typeFunctionName :: HashSet Text
- PostgresqlSyntax.KeywordSet: unreservedKeyword :: HashSet Text
- PostgresqlSyntax.Parsing: aExpr :: Parser AExpr
- PostgresqlSyntax.Parsing: aexprConst :: HeadedParsec Void Text AexprConst
- PostgresqlSyntax.Parsing: aliasClause :: HeadedParsec Void Text AliasClause
- PostgresqlSyntax.Parsing: allOp :: (Tokens strm ~ Text, Token strm ~ Char, Ord err, Stream strm) => HeadedParsec err strm AllOp
- PostgresqlSyntax.Parsing: allOrDistinct :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: anyKeyword :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => HeadedParsec e s Text
- PostgresqlSyntax.Parsing: anyName :: HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: anyOperator :: HeadedParsec Void Text AnyOperator
- PostgresqlSyntax.Parsing: arrayBounds :: Integral a => HeadedParsec Void Text (NonEmpty (Maybe a))
- PostgresqlSyntax.Parsing: arrayExprCont :: HeadedParsec Void Text (HeadedParsec Void Text ArrayExpr)
- PostgresqlSyntax.Parsing: ascDesc :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s AscDesc
- PostgresqlSyntax.Parsing: atEnd :: Parser a -> Parser a
- PostgresqlSyntax.Parsing: attrName :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: attrs :: HeadedParsec Void Text (NonEmpty Ident)
- PostgresqlSyntax.Parsing: bExpr :: HeadedParsec Void Text BExpr
- PostgresqlSyntax.Parsing: baseSimpleSelect :: HeadedParsec Void Text SimpleSelect
- PostgresqlSyntax.Parsing: bit :: HeadedParsec Void Text Bit
- PostgresqlSyntax.Parsing: cExpr :: HeadedParsec Void Text CExpr
- PostgresqlSyntax.Parsing: callStmt :: HeadedParsec Void Text CallStmt
- PostgresqlSyntax.Parsing: caseExpr :: HeadedParsec Void Text CaseExpr
- PostgresqlSyntax.Parsing: character :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Character
- PostgresqlSyntax.Parsing: class_ :: HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: colDefList :: HeadedParsec Void Text ColDefList
- PostgresqlSyntax.Parsing: colId :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: colLabel :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: collate :: HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: collateClause :: HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: columnref :: HeadedParsec Void Text Columnref
- PostgresqlSyntax.Parsing: commaSeparator :: Parser ()
- PostgresqlSyntax.Parsing: commonTableExpr :: HeadedParsec Void Text CommonTableExpr
- PostgresqlSyntax.Parsing: confExpr :: HeadedParsec Void Text ConfExpr
- PostgresqlSyntax.Parsing: constBit :: HeadedParsec Void Text ConstBit
- PostgresqlSyntax.Parsing: constCharacter :: HeadedParsec Void Text ConstCharacter
- PostgresqlSyntax.Parsing: constDatetime :: HeadedParsec Void Text ConstDatetime
- PostgresqlSyntax.Parsing: constTypename :: HeadedParsec Void Text ConstTypename
- PostgresqlSyntax.Parsing: cursorName :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: customizedAExpr :: HeadedParsec Void Text CExpr -> Parser AExpr
- PostgresqlSyntax.Parsing: customizedAnyName :: HeadedParsec Void Text Ident -> HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: customizedBExpr :: HeadedParsec Void Text CExpr -> HeadedParsec Void Text BExpr
- PostgresqlSyntax.Parsing: customizedCExpr :: HeadedParsec Void Text Columnref -> HeadedParsec Void Text CExpr
- PostgresqlSyntax.Parsing: customizedColumnref :: HeadedParsec Void Text Ident -> HeadedParsec Void Text Columnref
- PostgresqlSyntax.Parsing: deleteStmt :: HeadedParsec Void Text DeleteStmt
- PostgresqlSyntax.Parsing: dollarQuotedSconst :: Parser Text
- PostgresqlSyntax.Parsing: dotSeparator :: Parser ()
- PostgresqlSyntax.Parsing: elseClause :: HeadedParsec Void Text CaseDefault
- PostgresqlSyntax.Parsing: explicitRow :: HeadedParsec Void Text ExplicitRow
- PostgresqlSyntax.Parsing: exprList :: HeadedParsec Void Text ExprList
- PostgresqlSyntax.Parsing: exprListInParens :: HeadedParsec Void Text TypeModifiers
- PostgresqlSyntax.Parsing: extensionSimpleSelect :: Either SimpleSelect SelectWithParens -> HeadedParsec Void Text SimpleSelect
- PostgresqlSyntax.Parsing: extractArg :: HeadedParsec Void Text ExtractArg
- PostgresqlSyntax.Parsing: extractList :: HeadedParsec Void Text ExtractList
- PostgresqlSyntax.Parsing: fconst :: (Token strm ~ Char, Stream strm, RealFloat float, Ord err) => HeadedParsec err strm float
- PostgresqlSyntax.Parsing: filterClause :: HeadedParsec Void Text FilterClause
- PostgresqlSyntax.Parsing: filteredAExpr :: [Text] -> HeadedParsec Void Text AExpr
- PostgresqlSyntax.Parsing: filteredAnyName :: Foldable t => t Text -> HeadedParsec Void Text AnyName
- PostgresqlSyntax.Parsing: filteredColId :: Foldable t => t Text -> HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: filteredColumnref :: [Text] -> HeadedParsec Void Text Columnref
- PostgresqlSyntax.Parsing: firstOrNext :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: forLockingClause :: HeadedParsec Void Text ForLockingClause
- PostgresqlSyntax.Parsing: forLockingItem :: HeadedParsec Void Text ForLockingItem
- PostgresqlSyntax.Parsing: forLockingStrength :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => HeadedParsec e s ForLockingStrength
- PostgresqlSyntax.Parsing: frameBound :: HeadedParsec Void Text FrameBound
- PostgresqlSyntax.Parsing: frameClause :: HeadedParsec Void Text FrameClause
- PostgresqlSyntax.Parsing: frameClauseMode :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s FrameClauseMode
- PostgresqlSyntax.Parsing: frameExtent :: HeadedParsec Void Text FrameExtent
- PostgresqlSyntax.Parsing: fromClause :: HeadedParsec Void Text FromClause
- PostgresqlSyntax.Parsing: fromList :: HeadedParsec Void Text FromClause
- PostgresqlSyntax.Parsing: funcAliasClause :: HeadedParsec Void Text FuncAliasClause
- PostgresqlSyntax.Parsing: funcApplication :: HeadedParsec Void Text FuncApplication
- PostgresqlSyntax.Parsing: funcApplicationParams :: HeadedParsec Void Text FuncApplicationParams
- PostgresqlSyntax.Parsing: funcArgExpr :: HeadedParsec Void Text FuncArgExpr
- PostgresqlSyntax.Parsing: funcExpr :: HeadedParsec Void Text FuncExpr
- PostgresqlSyntax.Parsing: funcExprCommonSubexpr :: HeadedParsec Void Text FuncExprCommonSubexpr
- PostgresqlSyntax.Parsing: funcExprWindowless :: HeadedParsec Void Text FuncExprWindowless
- PostgresqlSyntax.Parsing: funcName :: Parser FuncName
- PostgresqlSyntax.Parsing: funcTable :: HeadedParsec Void Text FuncTable
- PostgresqlSyntax.Parsing: genericType :: HeadedParsec Void Text GenericType
- PostgresqlSyntax.Parsing: groupByItem :: HeadedParsec Void Text GroupByItem
- PostgresqlSyntax.Parsing: iconst :: (Token strm ~ Char, Stream strm, Integral decimal, Ord err) => HeadedParsec err strm decimal
- PostgresqlSyntax.Parsing: iconstOrFconst :: (Token strm ~ Char, Stream strm, RealFloat a1, Integral a2, Ord err) => HeadedParsec err strm (Either a2 a1)
- PostgresqlSyntax.Parsing: ident :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: implicitRow :: Parser ImplicitRow
- PostgresqlSyntax.Parsing: inBrackets :: Parser a -> Parser a
- PostgresqlSyntax.Parsing: inBracketsCont :: Parser a -> Parser (Parser a)
- PostgresqlSyntax.Parsing: inExpr :: HeadedParsec Void Text InExpr
- PostgresqlSyntax.Parsing: inParens :: Parser a -> Parser a
- PostgresqlSyntax.Parsing: inParensCont :: Parser a -> Parser (Parser a)
- PostgresqlSyntax.Parsing: inParensJoinedTable :: HeadedParsec Void Text JoinedTable
- PostgresqlSyntax.Parsing: inParensWithClause :: Parser clause -> Parser content -> Parser content
- PostgresqlSyntax.Parsing: inParensWithLabel :: (label -> content -> result) -> Parser label -> Parser content -> Parser result
- PostgresqlSyntax.Parsing: inSpace :: Parser a -> Parser a
- PostgresqlSyntax.Parsing: indexElem :: HeadedParsec Void Text IndexElem
- PostgresqlSyntax.Parsing: indexElemDef :: HeadedParsec Void Text IndexElemDef
- PostgresqlSyntax.Parsing: indexParams :: HeadedParsec Void Text (NonEmpty IndexElem)
- PostgresqlSyntax.Parsing: indirection :: HeadedParsec Void Text Indirection
- PostgresqlSyntax.Parsing: indirectionEl :: HeadedParsec Void Text IndirectionEl
- PostgresqlSyntax.Parsing: insertColumnItem :: HeadedParsec Void Text InsertColumnItem
- PostgresqlSyntax.Parsing: insertColumnList :: Parser InsertColumnList
- PostgresqlSyntax.Parsing: insertRest :: HeadedParsec Void Text InsertRest
- PostgresqlSyntax.Parsing: insertStmt :: HeadedParsec Void Text InsertStmt
- PostgresqlSyntax.Parsing: insertTarget :: HeadedParsec Void Text InsertTarget
- PostgresqlSyntax.Parsing: interval :: HeadedParsec Void Text Interval
- PostgresqlSyntax.Parsing: intervalSecond :: Integral a => HeadedParsec Void Text (Maybe a)
- PostgresqlSyntax.Parsing: joinQual :: HeadedParsec Void Text JoinQual
- PostgresqlSyntax.Parsing: joinType :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s JoinType
- PostgresqlSyntax.Parsing: joinedTable :: Parser JoinedTable
- PostgresqlSyntax.Parsing: keyphrase :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => Text -> HeadedParsec e s Text
- PostgresqlSyntax.Parsing: keyword :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => Text -> HeadedParsec e s Text
- PostgresqlSyntax.Parsing: keywordNameByPredicate :: (Token strm ~ Char, Tokens strm ~ Text, Stream strm, Ord err) => (Text -> Bool) -> HeadedParsec err strm Ident
- PostgresqlSyntax.Parsing: keywordNameFromSet :: (Token strm ~ Char, Tokens strm ~ Text, Stream strm, Ord err) => HashSet Text -> HeadedParsec err strm Ident
- PostgresqlSyntax.Parsing: lexicalExprBinOp :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => HeadedParsec e s Text
- PostgresqlSyntax.Parsing: limitClause :: HeadedParsec Void Text LimitClause
- PostgresqlSyntax.Parsing: listVariadicFuncApplicationParams :: HeadedParsec Void Text FuncApplicationParams
- PostgresqlSyntax.Parsing: materialized :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: mathOp :: (Token strm ~ Char, Stream strm, FoldCase (Tokens strm), IsString (Tokens strm), Ord err) => HeadedParsec err strm MathOp
- PostgresqlSyntax.Parsing: minusedExpr :: (Token strm ~ Char, Stream strm, Ord err) => HeadedParsec err strm b -> HeadedParsec err strm b
- PostgresqlSyntax.Parsing: name :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: nameList :: HeadedParsec Void Text (NonEmpty Ident)
- PostgresqlSyntax.Parsing: nonTrailingTableRef :: HeadedParsec Void Text TableRef
- PostgresqlSyntax.Parsing: normalFuncApplicationParams :: HeadedParsec Void Text FuncApplicationParams
- PostgresqlSyntax.Parsing: nowaitOrSkip :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: nullsOrder :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s NullsOrder
- PostgresqlSyntax.Parsing: numeric :: HeadedParsec Void Text Numeric
- PostgresqlSyntax.Parsing: offsetClause :: HeadedParsec Void Text OffsetClause
- PostgresqlSyntax.Parsing: offsetClauseParams :: HeadedParsec Void Text OffsetClause
- PostgresqlSyntax.Parsing: onConflict :: HeadedParsec Void Text OnConflict
- PostgresqlSyntax.Parsing: onConflictDo :: HeadedParsec Void Text OnConflictDo
- PostgresqlSyntax.Parsing: onExpressionsClause :: HeadedParsec Void Text ExprList
- PostgresqlSyntax.Parsing: op :: (Tokens strm ~ Text, Token strm ~ Char, Ord err, Stream strm) => HeadedParsec err strm Text
- PostgresqlSyntax.Parsing: optOrdinality :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Text
- PostgresqlSyntax.Parsing: optTempTableName :: HeadedParsec Void Text IntoClause
- PostgresqlSyntax.Parsing: overClause :: HeadedParsec Void Text OverClause
- PostgresqlSyntax.Parsing: overlapsSuffix :: AExpr -> Parser AExpr
- PostgresqlSyntax.Parsing: overlayList :: HeadedParsec Void Text OverlayList
- PostgresqlSyntax.Parsing: overlayPlacing :: HeadedParsec Void Text AExpr
- PostgresqlSyntax.Parsing: overrideKind :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s OverrideKind
- PostgresqlSyntax.Parsing: parenthesizedExprCExpr :: Parser CExpr
- PostgresqlSyntax.Parsing: partitionByClause :: HeadedParsec Void Text PartitionClause
- PostgresqlSyntax.Parsing: plusOrMinus :: (Token strm ~ Char, Stream strm, Ord err) => HeadedParsec err strm Bool
- PostgresqlSyntax.Parsing: plusedExpr :: (Token strm ~ Char, Stream strm, Ord err) => HeadedParsec err strm b -> HeadedParsec err strm b
- PostgresqlSyntax.Parsing: positionList :: HeadedParsec Void Text PositionList
- PostgresqlSyntax.Parsing: preparableStmt :: Parser PreparableStmt
- PostgresqlSyntax.Parsing: qualAllOp :: HeadedParsec Void Text QualAllOp
- PostgresqlSyntax.Parsing: qualOp :: HeadedParsec Void Text QualOp
- PostgresqlSyntax.Parsing: qualOpExpr :: HeadedParsec Void Text a -> (QualOp -> a -> b) -> HeadedParsec Void Text b
- PostgresqlSyntax.Parsing: qualifiedName :: HeadedParsec Void Text QualifiedName
- PostgresqlSyntax.Parsing: quotedName :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: quotedString :: Char -> Parser Text
- PostgresqlSyntax.Parsing: relationExpr :: HeadedParsec Void Text RelationExpr
- PostgresqlSyntax.Parsing: relationExprOptAlias :: [Text] -> HeadedParsec Void Text RelationExprOptAlias
- PostgresqlSyntax.Parsing: repeatableClause :: HeadedParsec Void Text RepeatableClause
- PostgresqlSyntax.Parsing: returningClause :: HeadedParsec Void Text ReturningClause
- PostgresqlSyntax.Parsing: row :: HeadedParsec Void Text Row
- PostgresqlSyntax.Parsing: rowOrRows :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: rowsfromItem :: HeadedParsec Void Text RowsfromItem
- PostgresqlSyntax.Parsing: rowsfromList :: HeadedParsec Void Text (NonEmpty RowsfromItem)
- PostgresqlSyntax.Parsing: run :: Parser a -> Text -> Either String a
- PostgresqlSyntax.Parsing: runWithPosError :: Parser a -> Text -> Either (NonEmpty (Int, String)) a
- PostgresqlSyntax.Parsing: sconst :: HeadedParsec Void Text Text
- PostgresqlSyntax.Parsing: selectBinOp :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s SelectBinOp
- PostgresqlSyntax.Parsing: selectClause :: HeadedParsec Void Text (Either SimpleSelect SelectWithParens)
- PostgresqlSyntax.Parsing: selectClauseBase :: HeadedParsec Void Text (Either SimpleSelect SelectWithParens)
- PostgresqlSyntax.Parsing: selectClauseSuffix :: Either SimpleSelect SelectWithParens -> HeadedParsec Void Text (Either SimpleSelect SelectWithParens)
- PostgresqlSyntax.Parsing: selectFetchFirstValue :: HeadedParsec Void Text SelectFetchFirstValue
- PostgresqlSyntax.Parsing: selectLimit :: HeadedParsec Void Text SelectLimit
- PostgresqlSyntax.Parsing: selectLimitValue :: HeadedParsec Void Text SelectLimitValue
- PostgresqlSyntax.Parsing: selectNoParens :: HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: selectNoParensAfterClause :: Maybe WithClause -> Either SimpleSelect SelectWithParens -> HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: selectStmt :: HeadedParsec Void Text SelectStmt
- PostgresqlSyntax.Parsing: selectWithParens :: HeadedParsec Void Text SelectWithParens
- PostgresqlSyntax.Parsing: selectWithParensBody :: Parser SelectWithParens
- PostgresqlSyntax.Parsing: setClause :: HeadedParsec Void Text SetClause
- PostgresqlSyntax.Parsing: setClauseList :: HeadedParsec Void Text (NonEmpty SetClause)
- PostgresqlSyntax.Parsing: setTarget :: HeadedParsec Void Text SetTarget
- PostgresqlSyntax.Parsing: setTargetList :: Parser (NonEmpty SetTarget)
- PostgresqlSyntax.Parsing: sharedSelectNoParens :: Maybe WithClause -> HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: simpleSelectNoParens :: HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: simpleTypename :: HeadedParsec Void Text SimpleTypename
- PostgresqlSyntax.Parsing: singleVariadicFuncApplicationParams :: HeadedParsec Void Text FuncApplicationParams
- PostgresqlSyntax.Parsing: sortBy :: HeadedParsec Void Text SortBy
- PostgresqlSyntax.Parsing: sortClause :: HeadedParsec Void Text SortClause
- PostgresqlSyntax.Parsing: starFuncApplicationParams :: (Token strm ~ Char, Stream strm, Ord err) => HeadedParsec err strm FuncApplicationParams
- PostgresqlSyntax.Parsing: subType :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s SubType
- PostgresqlSyntax.Parsing: subqueryOp :: HeadedParsec Void Text SubqueryOp
- PostgresqlSyntax.Parsing: substrFor :: HeadedParsec Void Text SubstrFor
- PostgresqlSyntax.Parsing: substrFrom :: HeadedParsec Void Text AExpr
- PostgresqlSyntax.Parsing: substrList :: HeadedParsec Void Text SubstrList
- PostgresqlSyntax.Parsing: substrListFromFor :: HeadedParsec Void Text SubstrListFromFor
- PostgresqlSyntax.Parsing: symbolicBinOpExpr :: t1 -> HeadedParsec Void Text t2 -> (t1 -> SymbolicExprBinOp -> t2 -> b) -> HeadedParsec Void Text b
- PostgresqlSyntax.Parsing: symbolicExprBinOp :: HeadedParsec Void Text SymbolicExprBinOp
- PostgresqlSyntax.Parsing: tableFuncElement :: HeadedParsec Void Text TableFuncElement
- PostgresqlSyntax.Parsing: tableFuncElementList :: HeadedParsec Void Text ColDefList
- PostgresqlSyntax.Parsing: tableRef :: HeadedParsec Void Text TableRef
- PostgresqlSyntax.Parsing: tablesampleClause :: HeadedParsec Void Text TablesampleClause
- PostgresqlSyntax.Parsing: targetEl :: HeadedParsec Void Text TargetEl
- PostgresqlSyntax.Parsing: targetList :: HeadedParsec Void Text (NonEmpty TargetEl)
- PostgresqlSyntax.Parsing: targeting :: HeadedParsec Void Text Targeting
- PostgresqlSyntax.Parsing: timezone :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => HeadedParsec e s Bool
- PostgresqlSyntax.Parsing: trailingJoinedTable :: TableRef -> HeadedParsec Void Text JoinedTable
- PostgresqlSyntax.Parsing: trailingTableRef :: TableRef -> HeadedParsec Void Text TableRef
- PostgresqlSyntax.Parsing: trimList :: HeadedParsec Void Text TrimList
- PostgresqlSyntax.Parsing: trimModifier :: (Tokens s ~ Text, Token s ~ Char, Ord e, Stream s) => HeadedParsec e s TrimModifier
- PostgresqlSyntax.Parsing: trueIfPresent :: Parser a -> Parser Bool
- PostgresqlSyntax.Parsing: type Parser = HeadedParsec Void Text
- PostgresqlSyntax.Parsing: typeFunctionName :: HeadedParsec Void Text Ident
- PostgresqlSyntax.Parsing: typeList :: Parser TypeList
- PostgresqlSyntax.Parsing: typeModifiers :: HeadedParsec Void Text TypeModifiers
- PostgresqlSyntax.Parsing: typecastExpr :: a -> (a -> Typename -> a) -> HeadedParsec Void Text a
- PostgresqlSyntax.Parsing: typename :: HeadedParsec Void Text Typename
- PostgresqlSyntax.Parsing: unparenthesizedSelectNoParens :: HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: updateStmt :: HeadedParsec Void Text UpdateStmt
- PostgresqlSyntax.Parsing: usingClause :: HeadedParsec Void Text UsingClause
- PostgresqlSyntax.Parsing: valuesClause :: HeadedParsec Void Text ValuesClause
- PostgresqlSyntax.Parsing: whenClause :: HeadedParsec Void Text WhenClause
- PostgresqlSyntax.Parsing: whereClause :: HeadedParsec Void Text WhereClause
- PostgresqlSyntax.Parsing: whereOrCurrentClause :: HeadedParsec Void Text WhereOrCurrentClause
- PostgresqlSyntax.Parsing: windowDefinition :: HeadedParsec Void Text WindowDefinition
- PostgresqlSyntax.Parsing: windowExclusionClause :: (Token s ~ Char, Tokens s ~ Text, Ord e, Stream s) => HeadedParsec e s WindowExclusionClause
- PostgresqlSyntax.Parsing: windowSpecification :: HeadedParsec Void Text WindowSpecification
- PostgresqlSyntax.Parsing: withClause :: HeadedParsec Void Text WithClause
- PostgresqlSyntax.Parsing: withSelectNoParens :: HeadedParsec Void Text SelectNoParens
- PostgresqlSyntax.Parsing: withinGroupClause :: HeadedParsec Void Text WithinGroupClause
- PostgresqlSyntax.Rendering: aExpr :: AExpr -> TextBuilder
- PostgresqlSyntax.Rendering: aExprReversableOp :: Bool -> AExprReversableOp -> TextBuilder
- PostgresqlSyntax.Rendering: aexprConst :: AexprConst -> TextBuilder
- PostgresqlSyntax.Rendering: aliasClause :: AliasClause -> TextBuilder
- PostgresqlSyntax.Rendering: allOp :: AllOp -> TextBuilder
- PostgresqlSyntax.Rendering: allOrDistinct :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: anyName :: AnyName -> TextBuilder
- PostgresqlSyntax.Rendering: anyOperator :: AnyOperator -> TextBuilder
- PostgresqlSyntax.Rendering: arrayBounds :: Foldable t => NonEmpty (t Int64) -> TextBuilder
- PostgresqlSyntax.Rendering: arrayExpr :: ArrayExpr -> TextBuilder
- PostgresqlSyntax.Rendering: arrayExprList :: ArrayExprList -> TextBuilder
- PostgresqlSyntax.Rendering: ascDesc :: IsString a => AscDesc -> a
- PostgresqlSyntax.Rendering: attrName :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: attrs :: Foldable t => t Ident -> TextBuilder
- PostgresqlSyntax.Rendering: bExpr :: BExpr -> TextBuilder
- PostgresqlSyntax.Rendering: bExprIsOp :: Bool -> BExprIsOp -> TextBuilder
- PostgresqlSyntax.Rendering: bit :: Bit -> TextBuilder
- PostgresqlSyntax.Rendering: cExpr :: CExpr -> TextBuilder
- PostgresqlSyntax.Rendering: callStmt :: CallStmt -> TextBuilder
- PostgresqlSyntax.Rendering: caseDefault :: CaseDefault -> TextBuilder
- PostgresqlSyntax.Rendering: caseExpr :: CaseExpr -> TextBuilder
- PostgresqlSyntax.Rendering: character :: (Semigroup a, IsString a) => Character -> a
- PostgresqlSyntax.Rendering: class_ :: AnyName -> TextBuilder
- PostgresqlSyntax.Rendering: colDefList :: ColDefList -> TextBuilder
- PostgresqlSyntax.Rendering: colId :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: colLabel :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: collate :: AnyName -> TextBuilder
- PostgresqlSyntax.Rendering: collateClause :: AnyName -> TextBuilder
- PostgresqlSyntax.Rendering: columnref :: Columnref -> TextBuilder
- PostgresqlSyntax.Rendering: commaNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder
- PostgresqlSyntax.Rendering: commonTableExpr :: CommonTableExpr -> TextBuilder
- PostgresqlSyntax.Rendering: confExpr :: ConfExpr -> TextBuilder
- PostgresqlSyntax.Rendering: constBit :: ConstBit -> TextBuilder
- PostgresqlSyntax.Rendering: constCharacter :: ConstCharacter -> TextBuilder
- PostgresqlSyntax.Rendering: constDatetime :: ConstDatetime -> TextBuilder
- PostgresqlSyntax.Rendering: constTypename :: ConstTypename -> TextBuilder
- PostgresqlSyntax.Rendering: cursorName :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: deleteStmt :: DeleteStmt -> TextBuilder
- PostgresqlSyntax.Rendering: explicitRow :: ExplicitRow -> TextBuilder
- PostgresqlSyntax.Rendering: exprList :: ExprList -> TextBuilder
- PostgresqlSyntax.Rendering: extractArg :: ExtractArg -> TextBuilder
- PostgresqlSyntax.Rendering: extractList :: ExtractList -> TextBuilder
- PostgresqlSyntax.Rendering: fconst :: Double -> TextBuilder
- PostgresqlSyntax.Rendering: filterClause :: FilterClause -> TextBuilder
- PostgresqlSyntax.Rendering: firstOrNext :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: forLockingClause :: ForLockingClause -> TextBuilder
- PostgresqlSyntax.Rendering: forLockingItem :: ForLockingItem -> TextBuilder
- PostgresqlSyntax.Rendering: forLockingStrength :: IsString a => ForLockingStrength -> a
- PostgresqlSyntax.Rendering: frameBound :: FrameBound -> TextBuilder
- PostgresqlSyntax.Rendering: frameClause :: FrameClause -> TextBuilder
- PostgresqlSyntax.Rendering: frameClauseMode :: IsString a => FrameClauseMode -> a
- PostgresqlSyntax.Rendering: frameExtent :: FrameExtent -> TextBuilder
- PostgresqlSyntax.Rendering: fromClause :: FromClause -> TextBuilder
- PostgresqlSyntax.Rendering: fromList :: FromClause -> TextBuilder
- PostgresqlSyntax.Rendering: funcAexprConstArgList :: FuncConstArgs -> TextBuilder
- PostgresqlSyntax.Rendering: funcAliasClause :: FuncAliasClause -> TextBuilder
- PostgresqlSyntax.Rendering: funcApplication :: FuncApplication -> TextBuilder
- PostgresqlSyntax.Rendering: funcApplicationParams :: FuncApplicationParams -> TextBuilder
- PostgresqlSyntax.Rendering: funcArgExpr :: FuncArgExpr -> TextBuilder
- PostgresqlSyntax.Rendering: funcExpr :: FuncExpr -> TextBuilder
- PostgresqlSyntax.Rendering: funcExprCommonSubexpr :: FuncExprCommonSubexpr -> TextBuilder
- PostgresqlSyntax.Rendering: funcExprWindownless :: FuncExprWindowless -> TextBuilder
- PostgresqlSyntax.Rendering: funcName :: FuncName -> TextBuilder
- PostgresqlSyntax.Rendering: funcTable :: FuncTable -> TextBuilder
- PostgresqlSyntax.Rendering: genericType :: GenericType -> TextBuilder
- PostgresqlSyntax.Rendering: groupByItem :: GroupByItem -> TextBuilder
- PostgresqlSyntax.Rendering: groupClause :: GroupClause -> TextBuilder
- PostgresqlSyntax.Rendering: havingClause :: HavingClause -> TextBuilder
- PostgresqlSyntax.Rendering: iconst :: Int64 -> TextBuilder
- PostgresqlSyntax.Rendering: ident :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: implicitRow :: ImplicitRow -> TextBuilder
- PostgresqlSyntax.Rendering: inBrackets :: TextBuilder -> TextBuilder
- PostgresqlSyntax.Rendering: inExpr :: InExpr -> TextBuilder
- PostgresqlSyntax.Rendering: inParens :: TextBuilder -> TextBuilder
- PostgresqlSyntax.Rendering: indexElem :: IndexElem -> TextBuilder
- PostgresqlSyntax.Rendering: indexElemDef :: IndexElemDef -> TextBuilder
- PostgresqlSyntax.Rendering: indexParams :: NonEmpty IndexElem -> TextBuilder
- PostgresqlSyntax.Rendering: indirection :: Indirection -> TextBuilder
- PostgresqlSyntax.Rendering: indirectionEl :: IndirectionEl -> TextBuilder
- PostgresqlSyntax.Rendering: insertColumnItem :: InsertColumnItem -> TextBuilder
- PostgresqlSyntax.Rendering: insertColumnList :: InsertColumnList -> TextBuilder
- PostgresqlSyntax.Rendering: insertRest :: InsertRest -> TextBuilder
- PostgresqlSyntax.Rendering: insertRestOverriding :: (Semigroup a, IsString a) => OverrideKind -> a
- PostgresqlSyntax.Rendering: insertStmt :: InsertStmt -> TextBuilder
- PostgresqlSyntax.Rendering: insertTarget :: InsertTarget -> TextBuilder
- PostgresqlSyntax.Rendering: intOrFloat :: Either Int64 Double -> TextBuilder
- PostgresqlSyntax.Rendering: interval :: Interval -> TextBuilder
- PostgresqlSyntax.Rendering: intervalSecond :: Maybe Int64 -> TextBuilder
- PostgresqlSyntax.Rendering: intoClause :: IntoClause -> TextBuilder
- PostgresqlSyntax.Rendering: joinQual :: JoinQual -> TextBuilder
- PostgresqlSyntax.Rendering: joinType :: (Semigroup a, IsString a) => JoinType -> a
- PostgresqlSyntax.Rendering: joinedTable :: JoinedTable -> TextBuilder
- PostgresqlSyntax.Rendering: lexemes :: [TextBuilder] -> TextBuilder
- PostgresqlSyntax.Rendering: limitClause :: LimitClause -> TextBuilder
- PostgresqlSyntax.Rendering: lockedRelsList :: NonEmpty QualifiedName -> TextBuilder
- PostgresqlSyntax.Rendering: materialization :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: mathOp :: MathOp -> TextBuilder
- PostgresqlSyntax.Rendering: name :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: nowaitOrSkip :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: nullsOrder :: IsString a => NullsOrder -> a
- PostgresqlSyntax.Rendering: numeric :: Numeric -> TextBuilder
- PostgresqlSyntax.Rendering: offsetClause :: OffsetClause -> TextBuilder
- PostgresqlSyntax.Rendering: onConflict :: OnConflict -> TextBuilder
- PostgresqlSyntax.Rendering: onConflictDo :: OnConflictDo -> TextBuilder
- PostgresqlSyntax.Rendering: onExpressionsClause :: ExprList -> TextBuilder
- PostgresqlSyntax.Rendering: op :: Text -> TextBuilder
- PostgresqlSyntax.Rendering: optAlias :: (Bool, Ident) -> TextBuilder
- PostgresqlSyntax.Rendering: optLexemes :: [Maybe TextBuilder] -> TextBuilder
- PostgresqlSyntax.Rendering: optTempTableName :: IntoClause -> TextBuilder
- PostgresqlSyntax.Rendering: overClause :: OverClause -> TextBuilder
- PostgresqlSyntax.Rendering: overlayList :: OverlayList -> TextBuilder
- PostgresqlSyntax.Rendering: overlayPlacing :: OverlayPlacing -> TextBuilder
- PostgresqlSyntax.Rendering: overrideKind :: IsString a => OverrideKind -> a
- PostgresqlSyntax.Rendering: partitionClause :: PartitionClause -> TextBuilder
- PostgresqlSyntax.Rendering: positionList :: PositionList -> TextBuilder
- PostgresqlSyntax.Rendering: prefixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder
- PostgresqlSyntax.Rendering: preparableStmt :: PreparableStmt -> TextBuilder
- PostgresqlSyntax.Rendering: qualAllOp :: QualAllOp -> TextBuilder
- PostgresqlSyntax.Rendering: qualOp :: QualOp -> TextBuilder
- PostgresqlSyntax.Rendering: qualifiedName :: QualifiedName -> TextBuilder
- PostgresqlSyntax.Rendering: relationExpr :: RelationExpr -> TextBuilder
- PostgresqlSyntax.Rendering: relationExprOptAlias :: RelationExprOptAlias -> TextBuilder
- PostgresqlSyntax.Rendering: repeatableClause :: RepeatableClause -> TextBuilder
- PostgresqlSyntax.Rendering: returningClause :: ReturningClause -> TextBuilder
- PostgresqlSyntax.Rendering: row :: Row -> TextBuilder
- PostgresqlSyntax.Rendering: rowOrRows :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: rowsfromItem :: RowsfromItem -> TextBuilder
- PostgresqlSyntax.Rendering: rowsfromList :: RowsfromList -> TextBuilder
- PostgresqlSyntax.Rendering: sconst :: Text -> TextBuilder
- PostgresqlSyntax.Rendering: selectBinOp :: IsString a => SelectBinOp -> a
- PostgresqlSyntax.Rendering: selectClause :: SelectClause -> TextBuilder
- PostgresqlSyntax.Rendering: selectFetchFirstValue :: SelectFetchFirstValue -> TextBuilder
- PostgresqlSyntax.Rendering: selectLimit :: SelectLimit -> TextBuilder
- PostgresqlSyntax.Rendering: selectLimitValue :: SelectLimitValue -> TextBuilder
- PostgresqlSyntax.Rendering: selectNoParens :: SelectNoParens -> TextBuilder
- PostgresqlSyntax.Rendering: selectStmt :: SelectStmt -> TextBuilder
- PostgresqlSyntax.Rendering: selectWithParens :: SelectWithParens -> TextBuilder
- PostgresqlSyntax.Rendering: setClause :: SetClause -> TextBuilder
- PostgresqlSyntax.Rendering: setClauseList :: SetClauseList -> TextBuilder
- PostgresqlSyntax.Rendering: setTarget :: SetTarget -> TextBuilder
- PostgresqlSyntax.Rendering: setTargetList :: SetTargetList -> TextBuilder
- PostgresqlSyntax.Rendering: simpleSelect :: SimpleSelect -> TextBuilder
- PostgresqlSyntax.Rendering: simpleTypename :: SimpleTypename -> TextBuilder
- PostgresqlSyntax.Rendering: sortBy :: SortBy -> TextBuilder
- PostgresqlSyntax.Rendering: sortClause :: SortClause -> TextBuilder
- PostgresqlSyntax.Rendering: spaceNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder
- PostgresqlSyntax.Rendering: subType :: IsString a => SubType -> a
- PostgresqlSyntax.Rendering: subqueryOp :: SubqueryOp -> TextBuilder
- PostgresqlSyntax.Rendering: substrFor :: SubstrFor -> TextBuilder
- PostgresqlSyntax.Rendering: substrFrom :: SubstrFrom -> TextBuilder
- PostgresqlSyntax.Rendering: substrList :: SubstrList -> TextBuilder
- PostgresqlSyntax.Rendering: substrListFromFor :: SubstrListFromFor -> TextBuilder
- PostgresqlSyntax.Rendering: suffixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder
- PostgresqlSyntax.Rendering: symbolicExprBinOp :: SymbolicExprBinOp -> TextBuilder
- PostgresqlSyntax.Rendering: tableFuncElement :: TableFuncElement -> TextBuilder
- PostgresqlSyntax.Rendering: tableFuncElementList :: ColDefList -> TextBuilder
- PostgresqlSyntax.Rendering: tableRef :: TableRef -> TextBuilder
- PostgresqlSyntax.Rendering: tablesampleClause :: TablesampleClause -> TextBuilder
- PostgresqlSyntax.Rendering: targetEl :: TargetEl -> TextBuilder
- PostgresqlSyntax.Rendering: targetList :: ReturningClause -> TextBuilder
- PostgresqlSyntax.Rendering: targeting :: Targeting -> TextBuilder
- PostgresqlSyntax.Rendering: timezone :: IsString a => Bool -> a
- PostgresqlSyntax.Rendering: toByteString :: TextBuilder -> ByteString
- PostgresqlSyntax.Rendering: toText :: TextBuilder -> Text
- PostgresqlSyntax.Rendering: trimList :: TrimList -> TextBuilder
- PostgresqlSyntax.Rendering: trimModifier :: IsString a => TrimModifier -> a
- PostgresqlSyntax.Rendering: typeFunctionName :: Ident -> TextBuilder
- PostgresqlSyntax.Rendering: typeList :: TypeList -> TextBuilder
- PostgresqlSyntax.Rendering: typeModifiers :: TypeModifiers -> TextBuilder
- PostgresqlSyntax.Rendering: typename :: Typename -> TextBuilder
- PostgresqlSyntax.Rendering: typenameArrayDimensions :: TypenameArrayDimensions -> TextBuilder
- PostgresqlSyntax.Rendering: typenameArrayDimensionsWithQuestionMark :: (TypenameArrayDimensions, b) -> TextBuilder
- PostgresqlSyntax.Rendering: updateStmt :: UpdateStmt -> TextBuilder
- PostgresqlSyntax.Rendering: usingClause :: UsingClause -> TextBuilder
- PostgresqlSyntax.Rendering: valuesClause :: ValuesClause -> TextBuilder
- PostgresqlSyntax.Rendering: verbalExprBinOp :: (Monoid b, IsString b) => Bool -> VerbalExprBinOp -> b
- PostgresqlSyntax.Rendering: whenClause :: WhenClause -> TextBuilder
- PostgresqlSyntax.Rendering: whereClause :: WhereClause -> TextBuilder
- PostgresqlSyntax.Rendering: whereOrCurrentClause :: WhereOrCurrentClause -> TextBuilder
- PostgresqlSyntax.Rendering: windowClause :: WindowClause -> TextBuilder
- PostgresqlSyntax.Rendering: windowDefinition :: WindowDefinition -> TextBuilder
- PostgresqlSyntax.Rendering: windowExclusionCause :: IsString a => WindowExclusionClause -> a
- PostgresqlSyntax.Rendering: windowSpecification :: WindowSpecification -> TextBuilder
- PostgresqlSyntax.Rendering: withClause :: WithClause -> TextBuilder
- PostgresqlSyntax.Rendering: withinGroupClause :: WithinGroupClause -> TextBuilder
- PostgresqlSyntax.Validation: op :: Text -> Maybe Text
+ PostgresqlSyntax: class IsAst a
+ PostgresqlSyntax: data Settings
+ PostgresqlSyntax: nullabilityMarkers :: Bool -> Settings
+ PostgresqlSyntax: parse :: IsAst a => Settings -> Text -> Either Text a
+ PostgresqlSyntax: parseWithPosError :: IsAst a => Settings -> Text -> Either (NonEmpty (Int, Text)) a
+ PostgresqlSyntax: parseWithSourcePosError :: IsAst a => Settings -> Text -> Either (NonEmpty (SourcePos, Text)) a
+ PostgresqlSyntax: parser :: IsAst a => Settings -> Parser a
+ PostgresqlSyntax: toText :: IsAst a => Settings -> a -> Text
+ PostgresqlSyntax: toTextBuilder :: IsAst a => Settings -> a -> TextBuilder

Files

bench/Main.hs view
@@ -4,7 +4,7 @@ -- Benchmark for the "keyword allocation cost in wide alternations" concern -- raised in <https://github.com/nikita-volkov/postgresql-syntax/issues/21>. ----- Compares the shipped, cheap 'PostgresqlSyntax.Parsing.keyword'+-- Compares the shipped, cheap 'PostgresqlSyntax.Helpers.Parsers.keyword' -- (a bare 'empty' on mismatch, no allocation beyond the consumed text) -- against a richer alternative that reports a proper \"expected one of ...\" -- error via 'Text.Megaparsec.failure' (as PR #20 proposed), the way it would@@ -12,27 +12,23 @@ -- -- Both implementations here pin the reported error offset via -- 'Megaparsec.setOffset', matching the fix applied to the shipped--- 'PostgresqlSyntax.Parsing.keyword' to stay correct under megaparsec+-- 'PostgresqlSyntax.Helpers.Parsers.keyword' to stay correct under megaparsec -- >=9.8's stricter '(<|>)' error-merging. That fix is what makes the rich -- variant produce complete "expecting ..." lists at all under current--- megaparsec; see 'PostgresqlSyntax.Parsing.keyword''s haddock.+-- megaparsec; see 'PostgresqlSyntax.Helpers.Parsers.keyword''s haddock. module Main where  import Criterion.Main import qualified Data.Char as Char-import qualified Data.HashSet as HashSet import qualified Data.Set as Set import qualified Data.Text as Text import HeadedMegaparsec (HeadedParsec, parse, toParsec)-import qualified Hedgehog.Gen as Gen-import qualified Main.Gen as SynGen-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import qualified PostgresqlSyntax.Parsing as Parsing-import qualified PostgresqlSyntax.Rendering as Rendering+import qualified PostgresqlSyntax+import qualified Test.QuickCheck as Qc import qualified Text.Megaparsec as Megaparsec import Prelude --- * Shared token scanner (mirrors 'PostgresqlSyntax.Parsing.anyKeyword')+-- * Shared token scanner (mirrors 'PostgresqlSyntax.Helpers.Parsers.anyKeyword')  firstIdentifierChar :: Char -> Bool firstIdentifierChar x = Char.isAlpha x || x == '_' || x >= '\200' && x <= '\377'@@ -76,6 +72,18 @@ runHeaded :: HeadedParsec Void Text.Text a -> Text.Text -> Either (Megaparsec.ParseErrorBundle Text.Text Void) a runHeaded p = Megaparsec.runParser (toParsec p <* Megaparsec.eof) "" +-- * Keyword word lists (sized to mirror the shipped keyword sets)++-- | ~90 words: the size of a typical mid-size dispatch, mirroring+-- @PostgresqlSyntax.KeywordSet.reservedKeyword@.+reservedWords :: [Text.Text]+reservedWords = ["all", "analyse", "analyze", "and", "any", "array", "as", "asc", "asymmetric", "both", "case", "cast", "check", "collate", "column", "constraint", "create", "current_catalog", "current_date", "current_role", "current_time", "current_timestamp", "current_user", "default", "deferrable", "desc", "distinct", "do", "else", "end", "except", "false", "fetch", "for", "foreign", "from", "grant", "group", "having", "in", "initially", "intersect", "into", "lateral", "leading", "limit", "localtime", "localtimestamp", "not", "null", "offset", "on", "only", "or", "order", "placing", "primary", "references", "returning", "select", "session_user", "some", "symmetric", "table", "then", "to", "trailing", "true", "union", "unique", "user", "using", "variadic", "when", "where", "window", "with"]++-- | ~440 words: the full reserved-word set, worst case, mirroring+-- @PostgresqlSyntax.KeywordSet.keyword@.+allWords :: [Text.Text]+allWords = ["abort", "absolute", "access", "action", "add", "admin", "after", "aggregate", "all", "also", "alter", "always", "analyse", "analyze", "and", "any", "array", "as", "asc", "assertion", "assignment", "asymmetric", "at", "attach", "attribute", "authorization", "backward", "before", "begin", "between", "bigint", "binary", "bit", "boolean", "both", "by", "cache", "call", "called", "cascade", "cascaded", "case", "cast", "catalog", "chain", "char", "character", "characteristics", "check", "checkpoint", "class", "close", "cluster", "coalesce", "collate", "collation", "column", "columns", "comment", "comments", "commit", "committed", "concurrently", "configuration", "conflict", "connection", "constraint", "constraints", "content", "continue", "conversion", "copy", "cost", "create", "cross", "csv", "cube", "current", "current_catalog", "current_date", "current_role", "current_schema", "current_time", "current_timestamp", "current_user", "cursor", "cycle", "data", "database", "day", "deallocate", "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred", "definer", "delete", "delimiter", "delimiters", "depends", "desc", "detach", "dictionary", "disable", "discard", "distinct", "do", "document", "domain", "double", "drop", "each", "else", "enable", "encoding", "encrypted", "end", "enum", "escape", "event", "except", "exclude", "excluding", "exclusive", "execute", "exists", "explain", "expression", "extension", "external", "extract", "false", "family", "fetch", "filter", "first", "float", "following", "for", "force", "foreign", "forward", "freeze", "from", "full", "function", "functions", "generated", "global", "grant", "granted", "greatest", "group", "grouping", "groups", "handler", "having", "header", "hold", "hour", "identity", "if", "ilike", "immediate", "immutable", "implicit", "import", "in", "include", "including", "increment", "index", "indexes", "inherit", "inherits", "initially", "inline", "inner", "inout", "input", "insensitive", "insert", "instead", "int", "integer", "intersect", "interval", "into", "invoker", "is", "isnull", "isolation", "join", "key", "label", "language", "large", "last", "lateral", "leading", "leakproof", "least", "left", "level", "like", "limit", "listen", "load", "local", "localtime", "localtimestamp", "location", "lock", "locked", "logged", "mapping", "match", "materialized", "maxvalue", "method", "minute", "minvalue", "mode", "month", "move", "name", "names", "national", "natural", "nchar", "new", "next", "nfc", "nfd", "nfkc", "nfkd", "no", "none", "normalize", "normalized", "not", "nothing", "notify", "notnull", "nowait", "null", "nullif", "nulls", "numeric", "object", "of", "off", "offset", "oids", "old", "on", "only", "operator", "option", "options", "or", "order", "ordinality", "others", "out", "outer", "over", "overlaps", "overlay", "overriding", "owned", "owner", "parallel", "parser", "partial", "partition", "passing", "password", "placing", "plans", "policy", "position", "preceding", "precision", "prepare", "prepared", "preserve", "primary", "prior", "privileges", "procedural", "procedure", "procedures", "program", "publication", "quote", "range", "read", "real", "reassign", "recheck", "recursive", "ref", "references", "referencing", "refresh", "reindex", "relative", "release", "rename", "repeatable", "replace", "replica", "reset", "restart", "restrict", "returning", "returns", "revoke", "right", "role", "rollback", "rollup", "routine", "routines", "row", "rows", "rule", "savepoint", "schema", "schemas", "scroll", "search", "second", "security", "select", "sequence", "sequences", "serializable", "server", "session", "session_user", "set", "setof", "sets", "share", "show", "similar", "simple", "skip", "smallint", "snapshot", "some", "sql", "stable", "standalone", "start", "statement", "statistics", "stdin", "stdout", "storage", "stored", "strict", "strip", "subscription", "substring", "support", "symmetric", "sysid", "system", "table", "tables", "tablesample", "tablespace", "temp", "template", "temporary", "text", "then", "ties", "time", "timestamp", "to", "trailing", "transaction", "transform", "treat", "trigger", "trim", "true", "truncate", "trusted", "type", "types", "uescape", "unbounded", "uncommitted", "unencrypted", "union", "unique", "unknown", "unlisten", "unlogged", "until", "update", "user", "using", "vacuum", "valid", "validate", "validator", "value", "values", "varchar", "variadic", "varying", "verbose", "version", "view", "views", "volatile", "when", "where", "whitespace", "window", "with", "within", "without", "work", "wrapper", "write", "xml", "xmlattributes", "xmlconcat", "xmlelement", "xmlexists", "xmlforest", "xmlnamespaces", "xmlparse", "xmlpi", "xmlroot", "xmlserialize", "xmltable", "year", "yes", "zone"]+ -- * Wide-alternation scenarios  -- | An alternation over every element of the given keyword list, dispatched@@ -87,13 +95,13 @@  main :: IO () main = do-  let reservedWords = HashSet.toList KeywordSet.reservedKeyword -- ~90 words: the size of a typical mid-size dispatch-      allWords = HashSet.toList KeywordSet.keyword -- ~440 words: the full reserved-word set, worst case-      lastOf xs = last xs+  let lastOf xs = last xs+      firstOf (x : _) = x+      firstOf [] = error "empty keyword list"       noMatchToken = "zzzznotakeyword" :: Text.Text -  corpus <- replicateM 500 (Gen.sample (Gen.resize 15 SynGen.preparableStmt))-  let corpusTexts = map (Rendering.toText . Rendering.preparableStmt) corpus+  corpus <- replicateM 500 (Qc.generate (Qc.resize 15 (Qc.arbitrary @PostgresqlSyntax.PreparableStmt)))+  let corpusTexts = map (PostgresqlSyntax.toText mempty) corpus    defaultMain     [ bgroup@@ -105,12 +113,12 @@             ]         | (label, kws) <- [("~90 words", reservedWords), ("~440 words", allWords)],           (scenario, token) <--            [ ("first match", head kws),+            [ ("first match", firstOf kws),               ("last match", lastOf kws),               ("no match", noMatchToken)             ]         ],       bgroup         "full grammar on generated corpus (reference, shipped keyword only)"-        [bench "500 generated preparableStmt" $ nf (map (either (const False) (const True) . Parsing.run Parsing.preparableStmt)) corpusTexts]+        [bench "500 generated preparableStmt" $ nf (map (either (const False) (const True) . PostgresqlSyntax.parse @PostgresqlSyntax.PreparableStmt mempty)) corpusTexts]     ]
− hedgehog-test/Main.hs
@@ -1,36 +0,0 @@-module Main where--import qualified Data.Text as Text-import Hedgehog-import Hedgehog.Main-import qualified Main.Gen as Gen-import qualified PostgresqlSyntax.Parsing as Parsing-import qualified PostgresqlSyntax.Rendering as Rendering-import Prelude--main :: IO ()-main =-  defaultMain-    [ checkParallel-        $ Group "Parsing a rendered AST produces the same AST"-        $ let p name amount gen parser renderer =-                (,) name-                  $ withDiscards (fromIntegral amount * 200)-                  $ withTests amount-                  $ property-                  $ do-                    ast <- forAll gen-                    let sql = Rendering.toText (renderer ast)-                     in do-                          footnote ("SQL: " <> Text.unpack sql)-                          case Parsing.run parser sql of-                            Left err -> do-                              footnote err-                              failure-                            Right ast' -> ast === ast'-           in [ p "typename" 10000 Gen.typename Parsing.typename Rendering.typename,-                p "tableRef" 10000 Gen.tableRef Parsing.tableRef Rendering.tableRef,-                p "aExpr" 60000 Gen.aExpr Parsing.aExpr Rendering.aExpr,-                p "preparableStmt" 30000 Gen.preparableStmt Parsing.preparableStmt Rendering.preparableStmt-              ]-    ]
− hedgehog-test/Main/Gen.hs
@@ -1,971 +0,0 @@-{-# OPTIONS_GHC -Wno-missing-signatures #-}--module Main.Gen where--import qualified Data.HashSet as HashSet-import qualified Data.List as List-import qualified Data.Text as Text-import Hedgehog (Gen)-import Hedgehog.Gen-import qualified Hedgehog.Range as Range-import PostgresqlSyntax.Ast-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import qualified PostgresqlSyntax.Validation as Validation-import Prelude hiding (bit, bool, filter, fromList, maybe, sortBy)---- * Generic--inSet set = filter (flip HashSet.member set)--notInSet set = filter (not . flip HashSet.member set)---- * Statements--preparableStmt =-  choice-    [ SelectPreparableStmt <$> selectStmt,-      InsertPreparableStmt <$> insertStmt,-      UpdatePreparableStmt <$> updateStmt,-      DeletePreparableStmt <$> deleteStmt,-      CallPreparableStmt <$> callStmt-    ]---- * Call--callStmt = CallStmt <$> funcApplication---- * Insert--insertStmt = InsertStmt <$> maybe withClause <*> insertTarget <*> insertRest <*> maybe onConflict <*> maybe returningClause--insertTarget = InsertTarget <$> qualifiedName <*> maybe colId--insertRest =-  choice-    [ SelectInsertRest <$> maybe insertColumnList <*> maybe overrideKind <*> selectStmt,-      pure DefaultValuesInsertRest-    ]--overrideKind = enumBounded--insertColumnList = nonEmpty (Range.exponential 1 7) insertColumnItem--insertColumnItem = InsertColumnItem <$> colId <*> maybe indirection--onConflict = OnConflict <$> maybe confExpr <*> onConflictDo--onConflictDo =-  choice-    [ UpdateOnConflictDo <$> setClauseList <*> maybe whereClause,-      pure NothingOnConflictDo-    ]--confExpr =-  choice-    [ WhereConfExpr <$> indexParams <*> maybe whereClause,-      ConstraintConfExpr <$> name-    ]--returningClause = targetList---- * Update--updateStmt = UpdateStmt <$> maybe withClause <*> relationExprOptAlias <*> setClauseList <*> maybe fromClause <*> maybe whereOrCurrentClause <*> maybe returningClause--setClauseList = nonEmpty (Range.exponential 1 10) setClause--setClause =-  choice-    [ TargetSetClause <$> setTarget <*> aExpr,-      TargetListSetClause <$> setTargetList <*> aExpr-    ]--setTarget = SetTarget <$> colId <*> maybe indirection--setTargetList = nonEmpty (Range.exponential 1 10) setTarget---- * Delete--deleteStmt = DeleteStmt <$> maybe withClause <*> relationExprOptAlias <*> maybe usingClause <*> maybe whereOrCurrentClause <*> maybe returningClause--usingClause = fromList---- * Select--selectStmt = Left <$> selectNoParens---- ** selectNoParens--selectNoParens =-  frequency-    [ (90, SelectNoParens <$> maybe withClause <*> (Left <$> simpleSelect) <*> maybe sortClause <*> maybe selectLimit <*> maybe forLockingClause),-      (10, clausePlusSurroundingsSelectNoParens)-    ]---- |--- A 'SelectNoParens' with at least one of its surrounding clauses present.------ The restriction matters for the @Right@ (parenthesised select) shape of the--- inner clause: @SelectNoParens Nothing (Right x) Nothing Nothing Nothing@--- renders to exactly the same text as @WithParensSelectWithParens x@, and the--- parser canonicalises that text to the latter — see the \"Canonical shape\"--- note on @PostgresqlSyntax.Parsing.selectWithParensBody@. So the degenerate--- combination is excluded here deliberately, rather than by accident of the--- generator's shape: it is the one tree in this family that the round-trip--- property cannot hold for.-clausePlusSurroundingsSelectNoParens = do-  clause <- selectClause-  -- At least one surrounding clause, so the SelectNoParens wrapper is-  -- load-bearing.-  (with, sort, limit, forLocking) <--    filter-      (\(a, b, c, d) -> any not [null a, null b, null c, null d])-      ((,,,) <$> maybe withClause <*> maybe sortClause <*> maybe selectLimit <*> maybe forLockingClause)-  return (SelectNoParens with clause sort limit forLocking)--terminalSelectNoParens =-  SelectNoParens <$> pure Nothing <*> (Left <$> terminalSimpleSelect) <*> pure Nothing <*> pure Nothing <*> pure Nothing---- ** selectWithParens--selectWithParens = sized $ \size ->-  if size <= 1-    then discard-    else-      frequency-        [ (95, NoParensSelectWithParens <$> selectNoParens),-          (5, WithParensSelectWithParens <$> selectWithParens)-        ]--terminalSelectWithParens = NoParensSelectWithParens <$> terminalSelectNoParens---- ** selectClause--selectClause =-  choice-    [ Left <$> simpleSelect,-      Right <$> small selectWithParens-    ]--nonTrailingSelectClause = Left <$> nonTrailingSimpleSelect---- ** simpleSelect--simpleSelect =-  choice-    [ normalSimpleSelect,-      tableSimpleSelect,-      valuesSimpleSelect,-      small nonTrailingSelectClause >>= binSimpleSelect-    ]--nonTrailingSimpleSelect = choice [normalSimpleSelect, valuesSimpleSelect, tableSimpleSelect]--normalSimpleSelect = NormalSimpleSelect <$> maybe targeting <*> maybe intoClause <*> maybe fromClause <*> maybe whereClause <*> maybe groupClause <*> maybe havingClause <*> maybe windowClause--tableSimpleSelect = TableSimpleSelect <$> relationExpr--valuesSimpleSelect = ValuesSimpleSelect <$> valuesClause--binSimpleSelect leftSelect =-  BinSimpleSelect <$> selectBinOp <*> pure leftSelect <*> maybe allOrDistinct <*> small selectClause--terminalSimpleSelect = pure (NormalSimpleSelect Nothing Nothing Nothing Nothing Nothing Nothing Nothing)---- * Targeting--targeting =-  choice-    [ NormalTargeting <$> targetList,-      AllTargeting <$> maybe targetList,-      DistinctTargeting <$> maybe (nonEmpty (Range.exponential 1 8) aExpr) <*> targetList-    ]--targetList = nonEmpty (Range.exponential 1 8) targetEl--targetEl =-  choice-    [ pure AsteriskTargetEl,-      AliasedExprTargetEl <$> aExpr <*> colLabel,-      ImplicitlyAliasedExprTargetEl <$> prefixAExpr <*> ident,-      ExprTargetEl <$> aExpr-    ]---- * BinSimpleSelect--selectBinOp = element [UnionSelectBinOp, IntersectSelectBinOp, ExceptSelectBinOp]---- * With Clause--withClause = WithClause <$> bool <*> nonEmpty (Range.exponential 1 7) commonTableExpr--commonTableExpr = CommonTableExpr <$> name <*> maybe (nonEmpty (Range.exponential 1 8) name) <*> maybe bool <*> small preparableStmt---- * Into Clause--intoClause = optTempTableName--optTempTableName =-  choice-    [ TemporaryOptTempTableName <$> bool <*> qualifiedName,-      TempOptTempTableName <$> bool <*> qualifiedName,-      LocalTemporaryOptTempTableName <$> bool <*> qualifiedName,-      LocalTempOptTempTableName <$> bool <*> qualifiedName,-      GlobalTemporaryOptTempTableName <$> bool <*> qualifiedName,-      GlobalTempOptTempTableName <$> bool <*> qualifiedName,-      UnloggedOptTempTableName <$> bool <*> qualifiedName,-      TableOptTempTableName <$> qualifiedName,-      QualifedOptTempTableName <$> qualifiedName-    ]---- * From Clause--fromList = nonEmpty (Range.exponential 1 8) tableRef--fromClause = fromList--tableRef = choice [relationExprTableRef, selectTableRef, joinTableRef]--relationExprTableRef = RelationExprTableRef <$> relationExpr <*> maybe aliasClause <*> maybe tablesampleClause--funcTableRef = FuncTableRef <$> bool <*> funcTable <*> maybe funcAliasClause--selectTableRef = SelectTableRef <$> bool <*> small selectWithParens <*> maybe aliasClause--joinTableRef = JoinTableRef <$> joinedTable <*> maybe aliasClause--relationExpr =-  choice-    [ SimpleRelationExpr <$> qualifiedName <*> bool,-      OnlyRelationExpr <$> qualifiedName <*> bool-    ]--relationExprOptAlias = RelationExprOptAlias <$> relationExpr <*> maybe ((,) <$> bool <*> colId)--tablesampleClause = TablesampleClause <$> funcName <*> exprList <*> maybe repeatableClause--repeatableClause = aExpr--funcTable =-  choice-    [ FuncExprFuncTable <$> funcExprWindowless <*> optOrdinality,-      RowsFromFuncTable <$> rowsfromList <*> optOrdinality-    ]--rowsfromItem = RowsfromItem <$> funcExprWindowless <*> maybe colDefList--rowsfromList = nonEmpty (Range.exponential 1 8) rowsfromItem--colDefList = tableFuncElementList--optOrdinality = bool--tableFuncElementList = nonEmpty (Range.exponential 1 7) tableFuncElement--tableFuncElement = TableFuncElement <$> colId <*> typename <*> maybe collateClause--collateClause = anyName--aliasClause = AliasClause <$> bool <*> name <*> maybe (nonEmpty (Range.exponential 1 8) name)--funcAliasClause =-  choice-    [ AliasFuncAliasClause <$> aliasClause,-      AsFuncAliasClause <$> tableFuncElementList,-      AsColIdFuncAliasClause <$> colId <*> tableFuncElementList,-      ColIdFuncAliasClause <$> colId <*> tableFuncElementList-    ]--joinedTable =-  frequency-    [ (5,) $ InParensJoinedTable <$> joinedTable,-      (95,) $ MethJoinedTable <$> joinMeth <*> tableRef <*> choice [relationExprTableRef, selectTableRef, funcTableRef]-    ]--joinMeth =-  choice-    [ pure CrossJoinMeth,-      QualJoinMeth <$> maybe joinType <*> joinQual,-      NaturalJoinMeth <$> maybe joinType-    ]--joinType =-  choice-    [ FullJoinType <$> bool,-      LeftJoinType <$> bool,-      RightJoinType <$> bool,-      pure InnerJoinType-    ]--joinQual =-  choice-    [ UsingJoinQual <$> nonEmpty (Range.exponential 1 8) name,-      OnJoinQual <$> aExpr-    ]---- * Group Clause--groupClause = nonEmpty (Range.exponential 1 8) groupByItem--groupByItem =-  choice-    [ ExprGroupByItem <$> aExpr,-      pure EmptyGroupingSetGroupByItem,-      RollupGroupByItem <$> nonEmpty (Range.exponential 1 8) aExpr,-      CubeGroupByItem <$> nonEmpty (Range.exponential 1 8) aExpr,-      GroupingSetsGroupByItem <$> nonEmpty (Range.exponential 1 3) groupByItem-    ]---- * Having Clause--havingClause = aExpr---- * Where Clause--whereClause = aExpr--whereOrCurrentClause =-  choice-    [ ExprWhereOrCurrentClause <$> aExpr,-      CursorWhereOrCurrentClause <$> cursorName-    ]---- * Window Clause--windowClause = nonEmpty (Range.exponential 1 8) windowDefinition--windowDefinition = WindowDefinition <$> name <*> windowSpecification--windowSpecification = WindowSpecification <$> maybe name <*> maybe (nonEmpty (Range.exponential 1 8) nonSuffixOpAExpr) <*> maybe sortClause <*> maybe frameClause--frameClause = FrameClause <$> frameClauseMode <*> frameExtent <*> maybe windowExclusionClause--frameClauseMode = element [RangeFrameClauseMode, RowsFrameClauseMode, GroupsFrameClauseMode]--frameExtent =-  choice-    [ SingularFrameExtent <$> frameBound,-      BetweenFrameExtent <$> frameBound <*> frameBound-    ]--frameBound =-  choice-    [ pure UnboundedPrecedingFrameBound,-      pure UnboundedFollowingFrameBound,-      pure CurrentRowFrameBound,-      PrecedingFrameBound <$> prefixAExpr,-      FollowingFrameBound <$> prefixAExpr-    ]--windowExclusionClause = element [CurrentRowWindowExclusionClause, GroupWindowExclusionClause, TiesWindowExclusionClause, NoOthersWindowExclusionClause]---- * Values Clause--valuesClause = nonEmpty (Range.exponential 1 8) (nonEmpty (Range.exponential 1 8) aExpr)---- * Sort Clause--sortClause = nonEmpty (Range.exponential 1 8) sortBy--sortBy =-  choice-    [ UsingSortBy <$> nonSuffixOpAExpr <*> qualAllOp <*> maybe nullsOrder,-      AscDescSortBy <$> nonSuffixOpAExpr <*> maybe ascDesc <*> maybe nullsOrder-    ]---- * All or distinct--allOrDistinct = bool---- * Limit--selectLimit =-  choice-    [ LimitOffsetSelectLimit <$> limitClause <*> offsetClause,-      OffsetLimitSelectLimit <$> offsetClause <*> limitClause,-      LimitSelectLimit <$> limitClause,-      OffsetSelectLimit <$> offsetClause-    ]--limitClause =-  choice-    [ LimitLimitClause <$> selectLimitValue <*> maybe aExpr,-      FetchOnlyLimitClause <$> bool <*> maybe selectFetchFirstValue <*> bool-    ]--selectFetchFirstValue =-  choice-    [ ExprSelectFetchFirstValue <$> cExpr,-      NumSelectFetchFirstValue <$> bool <*> iconstOrFconst-    ]--selectLimitValue =-  choice-    [ ExprSelectLimitValue <$> aExpr,-      pure AllSelectLimitValue-    ]--offsetClause =-  choice-    [ ExprOffsetClause <$> aExpr,-      FetchFirstOffsetClause <$> selectFetchFirstValue <*> bool-    ]---- * For Locking--forLockingClause =-  choice-    [ ItemsForLockingClause <$> nonEmpty (Range.exponential 1 8) forLockingItem,-      pure ReadOnlyForLockingClause-    ]--forLockingItem = ForLockingItem <$> forLockingStrength <*> maybe (nonEmpty (Range.exponential 1 8) qualifiedName) <*> maybe bool--forLockingStrength =-  element-    [ UpdateForLockingStrength,-      NoKeyUpdateForLockingStrength,-      ShareForLockingStrength,-      KeyForLockingStrength-    ]---- * Expressions--exprList = nonEmpty (Range.exponential 1 7) aExpr--aExpr =-  recursive-    choice-    [ CExprAExpr <$> cExpr,-      pure DefaultAExpr-    ]-    [ TypecastAExpr <$> prefixAExpr <*> typename,-      CollateAExpr <$> prefixAExpr <*> anyName,-      AtTimeZoneAExpr <$> prefixAExpr <*> aExpr,-      PlusAExpr <$> aExpr,-      MinusAExpr <$> aExpr,-      SymbolicBinOpAExpr <$> prefixAExpr <*> symbolicExprBinOp <*> aExpr,-      PrefixQualOpAExpr <$> qualOp <*> aExpr,-      SuffixQualOpAExpr <$> prefixAExpr <*> qualOp,-      AndAExpr <$> prefixAExpr <*> aExpr,-      OrAExpr <$> prefixAExpr <*> aExpr,-      NotAExpr <$> aExpr,-      VerbalExprBinOpAExpr <$> prefixAExpr <*> bool <*> verbalExprBinOp <*> prefixAExpr <*> maybe aExpr,-      ReversableOpAExpr <$> prefixAExpr <*> bool <*> aExprReversableOp,-      IsnullAExpr <$> prefixAExpr,-      NotnullAExpr <$> prefixAExpr,-      OverlapsAExpr <$> row <*> row,-      SubqueryAExpr <$> prefixAExpr <*> subqueryOp <*> subType <*> choice [Left <$> selectWithParens, Right <$> nonSelectAExpr],-      UniqueAExpr <$> selectWithParens-    ]--prefixAExpr =-  choice-    [ CExprAExpr <$> cExpr,-      pure DefaultAExpr,-      UniqueAExpr <$> selectWithParens-    ]--nonSuffixOpAExpr =-  recursive-    choice-    [ CExprAExpr <$> cExpr,-      pure DefaultAExpr-    ]-    [ TypecastAExpr <$> prefixAExpr <*> typename,-      CollateAExpr <$> prefixAExpr <*> anyName,-      AtTimeZoneAExpr <$> prefixAExpr <*> nonSuffixOpAExpr,-      PlusAExpr <$> nonSuffixOpAExpr,-      MinusAExpr <$> nonSuffixOpAExpr,-      SymbolicBinOpAExpr <$> prefixAExpr <*> symbolicExprBinOp <*> nonSuffixOpAExpr,-      PrefixQualOpAExpr <$> qualOp <*> nonSuffixOpAExpr,-      AndAExpr <$> prefixAExpr <*> nonSuffixOpAExpr,-      OrAExpr <$> prefixAExpr <*> nonSuffixOpAExpr,-      NotAExpr <$> nonSuffixOpAExpr,-      VerbalExprBinOpAExpr <$> prefixAExpr <*> bool <*> verbalExprBinOp <*> prefixAExpr <*> maybe nonSuffixOpAExpr,-      IsnullAExpr <$> prefixAExpr,-      NotnullAExpr <$> prefixAExpr,-      UniqueAExpr <$> selectWithParens-    ]--nonSelectAExpr =-  choice-    [ TypecastAExpr <$> prefixAExpr <*> typename,-      CollateAExpr <$> prefixAExpr <*> anyName,-      AtTimeZoneAExpr <$> prefixAExpr <*> aExpr,-      PlusAExpr <$> aExpr,-      MinusAExpr <$> aExpr,-      SymbolicBinOpAExpr <$> prefixAExpr <*> symbolicExprBinOp <*> aExpr,-      PrefixQualOpAExpr <$> qualOp <*> aExpr,-      SuffixQualOpAExpr <$> prefixAExpr <*> qualOp,-      AndAExpr <$> prefixAExpr <*> aExpr,-      OrAExpr <$> prefixAExpr <*> aExpr,-      NotAExpr <$> aExpr,-      VerbalExprBinOpAExpr <$> prefixAExpr <*> bool <*> verbalExprBinOp <*> prefixAExpr <*> maybe aExpr,-      ReversableOpAExpr <$> prefixAExpr <*> bool <*> aExprReversableOp,-      IsnullAExpr <$> prefixAExpr,-      NotnullAExpr <$> prefixAExpr,-      OverlapsAExpr <$> row <*> row,-      SubqueryAExpr <$> prefixAExpr <*> subqueryOp <*> subType <*> choice [Left <$> selectWithParens, Right <$> nonSelectAExpr],-      UniqueAExpr <$> selectWithParens-    ]--bExpr =-  recursive-    choice-    [ CExprBExpr <$> cExpr-    ]-    [ TypecastBExpr <$> prefixBExpr <*> typename,-      PlusBExpr <$> bExpr,-      MinusBExpr <$> bExpr,-      SymbolicBinOpBExpr <$> prefixBExpr <*> symbolicExprBinOp <*> bExpr,-      QualOpBExpr <$> qualOp <*> bExpr,-      IsOpBExpr <$> prefixBExpr <*> bool <*> bExprIsOp-    ]--prefixBExpr =-  choice-    [ CExprBExpr <$> cExpr-    ]--cExpr =-  recursive-    choice-    [ ColumnrefCExpr <$> columnref-    ]-    [ AexprConstCExpr <$> aexprConst,-      ParamCExpr <$> integral (Range.linear 1 19) <*> maybe indirection,-      InParensCExpr <$> nonSelectAExpr <*> maybe indirection,-      CaseCExpr <$> caseExpr,-      FuncCExpr <$> funcExpr,-      SelectWithParensCExpr <$> selectWithParens <*> maybe indirection,-      ExistsCExpr <$> selectWithParens,-      ArrayCExpr <$> choice [Left <$> selectWithParens, Right <$> arrayExpr],-      ExplicitRowCExpr <$> explicitRow,-      ImplicitRowCExpr <$> implicitRow,-      GroupingCExpr <$> exprList-    ]--caseExpr = CaseExpr <$> maybe aExpr <*> whenClauseList <*> maybe aExpr--whenClauseList = nonEmpty (Range.exponential 1 7) whenClause--whenClause = WhenClause <$> small aExpr <*> small aExpr--inExpr =-  choice-    [ SelectInExpr <$> NoParensSelectWithParens <$> selectNoParens,-      ExprListInExpr <$> exprList-    ]--arrayExpr =-  small-    $ choice-      [ ExprListArrayExpr <$> exprList,-        ArrayExprListArrayExpr <$> arrayExprList,-        pure EmptyArrayExpr-      ]--arrayExprList = nonEmpty (Range.exponential 1 4) arrayExpr--row =-  choice-    [ ExplicitRowRow <$> explicitRow,-      ImplicitRowRow <$> implicitRow-    ]--explicitRow = maybe exprList--implicitRow = ImplicitRow <$> exprList <*> aExpr---- ** FuncExpr--funcExpr =-  choice-    [ ApplicationFuncExpr <$> funcApplication <*> maybe withinGroupClause <*> maybe filterClause <*> maybe overClause,-      SubexprFuncExpr <$> funcExprCommonSubexpr-    ]--funcExprWindowless =-  choice-    [ ApplicationFuncExprWindowless <$> funcApplication,-      CommonSubexprFuncExprWindowless <$> funcExprCommonSubexpr-    ]--funcApplication = FuncApplication <$> funcName <*> maybe funcApplicationParams--funcApplicationParams =-  choice-    [ NormalFuncApplicationParams <$> maybe allOrDistinct <*> nonEmpty (Range.exponential 1 8) funcArgExpr <*> maybe sortClause,-      VariadicFuncApplicationParams <$> maybe (nonEmpty (Range.exponential 1 8) funcArgExpr) <*> funcArgExpr <*> maybe sortClause,-      pure StarFuncApplicationParams-    ]--funcArgExpr =-  choice-    [ ExprFuncArgExpr <$> small aExpr,-      ColonEqualsFuncArgExpr <$> name <*> small aExpr,-      EqualsGreaterFuncArgExpr <$> name <*> small aExpr-    ]--withinGroupClause = sortClause--filterClause = aExpr--overClause = choice [WindowOverClause <$> windowSpecification, ColIdOverClause <$> colId]--funcExprCommonSubexpr =-  choice-    [ CollationForFuncExprCommonSubexpr <$> aExpr,-      pure CurrentDateFuncExprCommonSubexpr,-      CurrentTimeFuncExprCommonSubexpr <$> maybe iconst,-      CurrentTimestampFuncExprCommonSubexpr <$> maybe iconst,-      LocalTimeFuncExprCommonSubexpr <$> maybe iconst,-      LocalTimestampFuncExprCommonSubexpr <$> maybe iconst,-      pure CurrentRoleFuncExprCommonSubexpr,-      pure CurrentUserFuncExprCommonSubexpr,-      pure SessionUserFuncExprCommonSubexpr,-      pure UserFuncExprCommonSubexpr,-      pure CurrentCatalogFuncExprCommonSubexpr,-      pure CurrentSchemaFuncExprCommonSubexpr,-      CastFuncExprCommonSubexpr <$> aExpr <*> typename,-      ExtractFuncExprCommonSubexpr <$> maybe extractList,-      OverlayFuncExprCommonSubexpr <$> overlayList,-      PositionFuncExprCommonSubexpr <$> maybe positionList,-      SubstringFuncExprCommonSubexpr <$> maybe substrList,-      TreatFuncExprCommonSubexpr <$> aExpr <*> typename,-      TrimFuncExprCommonSubexpr <$> maybe trimModifier <*> trimList,-      NullIfFuncExprCommonSubexpr <$> aExpr <*> aExpr,-      CoalesceFuncExprCommonSubexpr <$> exprList,-      GreatestFuncExprCommonSubexpr <$> exprList,-      LeastFuncExprCommonSubexpr <$> exprList-    ]--extractList = ExtractList <$> extractArg <*> aExpr--extractArg =-  choice-    [ IdentExtractArg <$> ident,-      pure YearExtractArg,-      pure MonthExtractArg,-      pure DayExtractArg,-      pure HourExtractArg,-      pure MinuteExtractArg,-      pure SecondExtractArg,-      SconstExtractArg <$> sconst-    ]--overlayList = OverlayList <$> aExpr <*> overlayPlacing <*> substrFrom <*> maybe substrFor--overlayPlacing = aExpr--positionList = PositionList <$> bExpr <*> bExpr--substrList =-  choice-    [ ExprSubstrList <$> aExpr <*> substrListFromFor,-      ExprListSubstrList <$> exprList-    ]--substrListFromFor =-  choice-    [ FromForSubstrListFromFor <$> substrFrom <*> substrFor,-      ForFromSubstrListFromFor <$> substrFor <*> substrFrom,-      FromSubstrListFromFor <$> substrFrom,-      ForSubstrListFromFor <$> substrFor-    ]--substrFrom = aExpr--substrFor = aExpr--trimModifier = enumBounded--trimList =-  choice-    [ ExprFromExprListTrimList <$> aExpr <*> exprList,-      FromExprListTrimList <$> exprList,-      ExprListTrimList <$> exprList-    ]---- * Operators--qualOp = choice [OpQualOp <$> op, OperatorQualOp <$> anyOperator]--qualAllOp =-  choice-    [ AllQualAllOp <$> allOp,-      AnyQualAllOp <$> anyOperator-    ]--op = do-  a <- text (Range.exponential 1 7) (listElement "+-*/<>=~!@#%^&|`?")-  case Validation.op a of-    Nothing -> return a-    _ -> discard--anyOperator =-  recursive-    choice-    [ AllOpAnyOperator <$> allOp-    ]-    [ QualifiedAnyOperator <$> colId <*> anyOperator-    ]--allOp = choice [OpAllOp <$> op, MathAllOp <$> mathOp]--mathOp = enumBounded--symbolicExprBinOp =-  choice-    [ MathSymbolicExprBinOp <$> mathOp,-      QualSymbolicExprBinOp <$> qualOp-    ]--binOp = element (toList KeywordSet.symbolicBinOp <> ["AND", "OR", "IS DISTINCT FROM", "IS NOT DISTINCT FROM"])--verbalExprBinOp = enumBounded--aExprReversableOp =-  choice-    [ pure NullAExprReversableOp,-      pure TrueAExprReversableOp,-      pure FalseAExprReversableOp,-      pure UnknownAExprReversableOp,-      DistinctFromAExprReversableOp <$> aExpr,-      OfAExprReversableOp <$> typeList,-      BetweenAExprReversableOp <$> bool <*> bExpr <*> aExpr,-      BetweenSymmetricAExprReversableOp <$> bExpr <*> aExpr,-      InAExprReversableOp <$> inExpr,-      pure DocumentAExprReversableOp-    ]--bExprIsOp =-  choice-    [ DistinctFromBExprIsOp <$> bExpr,-      OfBExprIsOp <$> typeList,-      pure DocumentBExprIsOp-    ]--subqueryOp =-  choice-    [ AllSubqueryOp <$> allOp,-      AnySubqueryOp <$> anyOperator,-      LikeSubqueryOp <$> bool,-      IlikeSubqueryOp <$> bool-    ]---- * Constants--aexprConst =-  choice-    [ IAexprConst <$> iconst,-      FAexprConst <$> fconst,-      SAexprConst <$> sconst,-      BAexprConst <$> text (Range.exponential 1 100) (listElement "01"),-      XAexprConst <$> text (Range.exponential 1 100) (listElement "0123456789abcdefABCDEF"),-      FuncAexprConst <$> funcName <*> maybe funcConstArgs <*> sconst,-      ConstTypenameAexprConst <$> constTypename <*> sconst,-      StringIntervalAexprConst <$> sconst <*> maybe interval,-      IntIntervalAexprConst <$> integral (Range.exponential 0 2309482309483029) <*> sconst,-      BoolAexprConst <$> bool,-      pure NullAexprConst-    ]--funcConstArgs = FuncConstArgs <$> nonEmpty (Range.exponential 1 7) funcArgExpr <*> maybe sortClause--constTypename =-  choice-    [ NumericConstTypename <$> numeric,-      ConstBitConstTypename <$> constBit,-      ConstCharacterConstTypename <$> constCharacter,-      ConstDatetimeConstTypename <$> constDatetime-    ]--numeric =-  choice-    [ pure IntNumeric,-      pure IntegerNumeric,-      pure SmallintNumeric,-      pure BigintNumeric,-      pure RealNumeric,-      FloatNumeric <$> maybe iconst,-      pure DoublePrecisionNumeric,-      DecimalNumeric <$> maybe (nonEmpty (Range.exponential 1 7) (small aExpr)),-      DecNumeric <$> maybe (nonEmpty (Range.exponential 1 7) (small aExpr)),-      NumericNumeric <$> maybe (nonEmpty (Range.exponential 1 7) (small aExpr)),-      pure BooleanNumeric-    ]--bit = Bit <$> bool <*> maybe (nonEmpty (Range.exponential 1 7) (small aExpr))--constBit = bit--constCharacter = ConstCharacter <$> character <*> maybe iconst--character =-  choice-    [ CharacterCharacter <$> bool,-      CharCharacter <$> bool,-      pure VarcharCharacter,-      NationalCharacterCharacter <$> bool,-      NationalCharCharacter <$> bool,-      NcharCharacter <$> bool-    ]--constDatetime =-  choice-    [ TimestampConstDatetime <$> maybe iconst <*> maybe bool,-      TimeConstDatetime <$> maybe iconst <*> maybe bool-    ]--interval =-  choice-    [ pure YearInterval,-      pure MonthInterval,-      pure DayInterval,-      pure HourInterval,-      pure MinuteInterval,-      SecondInterval <$> intervalSecond,-      pure YearToMonthInterval,-      pure DayToHourInterval,-      pure DayToMinuteInterval,-      DayToSecondInterval <$> intervalSecond,-      pure HourToMinuteInterval,-      HourToSecondInterval <$> intervalSecond,-      MinuteToSecondInterval <$> intervalSecond-    ]--intervalSecond = maybe iconst--sconst = text (Range.exponential 0 1000) unicode--iconstOrFconst = choice [Left <$> iconst <|> Right <$> fconst]--fconst =-  filter (\a -> fromIntegral (round a :: Int) /= a)-    $ realFrac_ (Range.exponentialFloat 0 309457394857984375983475943)--iconst = integral (Range.exponential 0 maxBound)---- * Types--nullable = pure False--arrayDimensionsAmount = int (Range.exponential 0 4)---- ** Typename--typename = Typename <$> bool <*> simpleTypename <*> pure False <*> maybe ((,) <$> typenameArrayDimensions <*> pure False)--typenameArrayDimensions =-  choice-    [ BoundsTypenameArrayDimensions <$> arrayBounds,-      ExplicitTypenameArrayDimensions <$> maybe iconst-    ]--arrayBounds = nonEmpty (Range.exponential 1 4) (maybe iconst)--simpleTypename =-  choice-    [ GenericTypeSimpleTypename <$> genericType,-      NumericSimpleTypename <$> numeric,-      BitSimpleTypename <$> bit,-      CharacterSimpleTypename <$> character,-      ConstDatetimeSimpleTypename <$> constDatetime,-      ConstIntervalSimpleTypename <$> choice [Left <$> maybe interval, Right <$> iconst]-    ]--genericType = GenericType <$> typeFunctionName <*> maybe attrs <*> maybe typeModifiers--attrs = nonEmpty (Range.exponential 1 10) attrName--typeModifiers = exprList--typeList = nonEmpty (Range.exponential 1 7) typename--subType = enumBounded---- * Names--columnref = Columnref <$> colId <*> maybe indirection--keywordNotInSet = \set -> notInSet set $ do-  a <- element startList-  b <- text (Range.linear 1 29) (element contList)-  return (Text.cons a b)-  where-    startList = "abcdefghijklmnopqrstuvwxyz_" <> List.filter isLower (enumFromTo '\200' '\377')-    contList = startList <> "0123456789$"--ident = identWithSet mempty--name = identWithSet KeywordSet.colId--cursorName = name--identWithSet set =-  frequency-    [ (95,) $ UnquotedIdent <$> (keywordNotInSet . HashSet.difference KeywordSet.keyword) set,-      (5,) $ QuotedIdent <$> text (Range.linear 1 30) quotedChar-    ]--qualifiedName =-  choice-    [ SimpleQualifiedName <$> name,-      IndirectedQualifiedName <$> name <*> indirection-    ]--indirection = nonEmpty (Range.linear 1 3) indirectionEl--indirectionEl =-  choice-    [ AttrNameIndirectionEl <$> name,-      pure AllIndirectionEl,-      ExprIndirectionEl <$> (small aExpr),-      SliceIndirectionEl <$> maybe (small aExpr) <*> maybe (small aExpr)-    ]--quotedChar = filter (not . isControl) unicode--colId = name--colLabel = name--attrName = colLabel--typeFunctionName = identWithSet KeywordSet.typeFunctionName--funcName =-  choice-    [ TypeFuncName <$> typeFunctionName,-      IndirectedFuncName <$> colId <*> indirection-    ]--anyName = AnyName <$> colId <*> maybe attrs---- * Indexes--indexParams = nonEmpty (Range.exponential 1 5) indexElem--indexElem = IndexElem <$> indexElemDef <*> maybe collate <*> maybe class_ <*> maybe ascDesc <*> maybe nullsOrder--indexElemDef =-  choice-    [ IdIndexElemDef <$> colId,-      FuncIndexElemDef <$> funcExprWindowless,-      ExprIndexElemDef <$> aExpr-    ]--collate = anyName--class_ = anyName--ascDesc = enumBounded--nullsOrder = enumBounded---- * Helpers--listElement :: [a] -> Gen a-listElement = element
+ hspec-test/Ast/AExprReversableOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AExprReversableOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AExprReversableOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AExprReversableOp+  itSatisfiesArbitrary @AExprReversableOp
+ hspec-test/Ast/AExprSpec.hs view
@@ -0,0 +1,75 @@+module Ast.AExprSpec (spec) where++import qualified Data.Text as Text+import Helpers.Specs+import PostgresqlSyntax.Ast.AExpr+import PostgresqlSyntax.Ast.CExpr+import PostgresqlSyntax.Ast.Columnref+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.VerbalExprBinOp+import PostgresqlSyntax.IsAst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @AExpr+  itSatisfiesArbitrary @AExpr+  describe "Postgres grammar conformance" $ do+    -- gram.y:15985,15987 have only @a_expr qual_Op a_expr@ and+    -- @qual_Op a_expr@ — the postfix @a_expr qual_Op@ form was removed+    -- from Postgres in v14.+    describe "rejects postfix operators" $ do+      itRejects @AExpr "1 +#"+      itRejects @AExpr "1 OPERATOR(pg_catalog.+#)"+      itRejects @AExpr "a +#"+  describe "Nesting depth" $ do+    itParsesWithin @AExpr 5 (Text.replicate 50 "(" <> "a + b" <> Text.replicate 50 ")")+    let terms off = Text.intercalate " + " ["coalesce(c" <> Text.pack (show (off + i)) <> ", 0)" | i <- [1 .. 24 :: Int]]+        coalesceSumInput = Text.replicate 6 "(" <> "(" <> terms 0 <> ") - (" <> terms 24 <> ")" <> Text.replicate 6 ")"+    itParsesWithin @AExpr 5 coalesceSumInput+    it "OVERLAPS still parses" $ do+      let render :: AExpr -> Text+          render = toText mempty+      fmap render (parse @AExpr mempty "(1, 2) overlaps (3, 4)") `shouldBe` Right "(1, 2) OVERLAPS (3, 4)"+      fmap render (parse @AExpr mempty "row(1, 2) overlaps row(3, 4)") `shouldBe` Right "ROW (1, 2) OVERLAPS ROW (3, 4)"+  describe "LIKE/ILIKE/SIMILAR TO ESCAPE rhs" $ do+    -- Regression for a bug introduced in 92a4d96: the ESCAPE-clause guard on+    -- the LIKE/ILIKE/SIMILAR TO pattern operand (`d`) was applied whenever an+    -- ESCAPE clause was present at all, instead of only when `d` is itself an+    -- unbounded shape. That spuriously parenthesized bounded operands (a+    -- plain column reference here), producing an extra 'InParensCExpr' layer+    -- on reparse that the original AST never had.+    let render :: AExpr -> Text+        render = toText mempty+        roundtrip sql = fmap render (parse @AExpr mempty sql)+    it "does not add parens around a bounded column-reference rhs" $ do+      roundtrip "a LIKE b ESCAPE 'x'" `shouldBe` Right "a LIKE b ESCAPE 'x'"+    it "does not add parens around a bounded ILIKE rhs" $ do+      roundtrip "a ILIKE b ESCAPE 'x'" `shouldBe` Right "a ILIKE b ESCAPE 'x'"+    it "does not add parens around a bounded SIMILAR TO rhs" $ do+      roundtrip "a SIMILAR TO b ESCAPE 'x'" `shouldBe` Right "a SIMILAR TO b ESCAPE 'x'"+    it "still parenthesizes an unbounded (nested, escape-less LIKE) rhs" $ do+      -- Constructed directly rather than by parsing a string: parsing+      -- "a LIKE b LIKE c ESCAPE 'x'" greedily binds the ESCAPE to the+      -- innermost LIKE (its own @d@ operand is unrestricted @a_expr@), so it+      -- can't reach the shape below by parsing alone. The shape is real+      -- though: an unbounded, escape-less nested 'VerbalExprBinOpAExpr' as+      -- the rhs of an outer production that itself has an ESCAPE clause. Left+      -- unparenthesized, rendering it bare would let a reparse of the outer+      -- ESCAPE bind to the inner LIKE instead, changing the AST.+      -- Reparsing always wraps a parenthesized operand in an explicit+      -- 'InParensCExpr' (parens are themselves a production), so the+      -- fixpoint of render/parse is the parenthesized form, not the bare+      -- @outer@ below — that's expected and matches how+      -- 'PostgresqlSyntax.Ast.AExpr.Qc.Arbitrary'\'s generator pre-wraps+      -- this same shape. What matters here is that the parens are present at+      -- all, and that the fixpoint is stable.+      let colref name = CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent name) Nothing))+          innerD = VerbalExprBinOpAExpr (colref "b") False LikeVerbalExprBinOp (colref "c") Nothing+          outer = VerbalExprBinOpAExpr (colref "a") False LikeVerbalExprBinOp innerD (Just (colref "e"))+          wrappedOuter = VerbalExprBinOpAExpr (colref "a") False LikeVerbalExprBinOp (CExprAExpr (InParensCExpr innerD Nothing)) (Just (colref "e"))+          sql = render outer+      sql `shouldBe` "a LIKE (b LIKE c) ESCAPE e"+      parse @AExpr mempty sql `shouldBe` Right wrappedOuter+      fmap render (parse @AExpr mempty sql) `shouldBe` Right sql
+ hspec-test/Ast/AexprConstSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AexprConstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AexprConst+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AexprConst+  itSatisfiesArbitrary @AexprConst
+ hspec-test/Ast/AliasClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AliasClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AliasClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AliasClause+  itSatisfiesArbitrary @AliasClause
+ hspec-test/Ast/AllOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AllOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AllOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AllOp+  itSatisfiesArbitrary @AllOp
+ hspec-test/Ast/AnyNameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AnyNameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AnyName+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AnyName+  itSatisfiesArbitrary @AnyName
+ hspec-test/Ast/AnyOperatorSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AnyOperatorSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AnyOperator+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AnyOperator+  itSatisfiesArbitrary @AnyOperator
+ hspec-test/Ast/ArrayBoundsSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ArrayBoundsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ArrayBounds+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ArrayBounds+  itSatisfiesArbitrary @ArrayBounds
+ hspec-test/Ast/ArrayExprListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ArrayExprListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ArrayExprList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ArrayExprList+  itSatisfiesArbitrary @ArrayExprList
+ hspec-test/Ast/ArrayExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ArrayExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ArrayExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ArrayExpr+  itSatisfiesArbitrary @ArrayExpr
+ hspec-test/Ast/AscDescSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AscDescSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.AscDesc+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @AscDesc+  itSatisfiesArbitrary @AscDesc
+ hspec-test/Ast/AttrsSpec.hs view
@@ -0,0 +1,10 @@+module Ast.AttrsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Attrs+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Attrs+  itSatisfiesArbitrary @Attrs
+ hspec-test/Ast/BExprIsOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.BExprIsOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.BExprIsOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @BExprIsOp+  itSatisfiesArbitrary @BExprIsOp
+ hspec-test/Ast/BExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.BExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.BExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @BExpr+  itSatisfiesArbitrary @BExpr
+ hspec-test/Ast/BconstSpec.hs view
@@ -0,0 +1,10 @@+module Ast.BconstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Bconst+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Bconst+  itSatisfiesArbitrary @Bconst
+ hspec-test/Ast/BitSpec.hs view
@@ -0,0 +1,10 @@+module Ast.BitSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Bit+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Bit+  itSatisfiesArbitrary @Bit
+ hspec-test/Ast/CExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.CExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.CExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @CExpr+  itSatisfiesArbitrary @CExpr
+ hspec-test/Ast/CallStmtSpec.hs view
@@ -0,0 +1,10 @@+module Ast.CallStmtSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.CallStmt+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @CallStmt+  itSatisfiesArbitrary @CallStmt
+ hspec-test/Ast/CaseExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.CaseExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.CaseExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @CaseExpr+  itSatisfiesArbitrary @CaseExpr
+ hspec-test/Ast/CharacterSpec.hs view
@@ -0,0 +1,10 @@+module Ast.CharacterSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Character+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Character+  itSatisfiesArbitrary @Character
+ hspec-test/Ast/ColumnrefSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ColumnrefSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Columnref+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Columnref+  itSatisfiesArbitrary @Columnref
+ hspec-test/Ast/CommonTableExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.CommonTableExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.CommonTableExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @CommonTableExpr+  itSatisfiesArbitrary @CommonTableExpr
+ hspec-test/Ast/ConfExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ConfExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ConfExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ConfExpr+  itSatisfiesArbitrary @ConfExpr
+ hspec-test/Ast/ConstCharacterSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ConstCharacterSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ConstCharacter+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ConstCharacter+  itSatisfiesArbitrary @ConstCharacter
+ hspec-test/Ast/ConstDatetimeSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ConstDatetimeSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ConstDatetime+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ConstDatetime+  itSatisfiesArbitrary @ConstDatetime
+ hspec-test/Ast/ConstTypenameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ConstTypenameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ConstTypename+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ConstTypename+  itSatisfiesArbitrary @ConstTypename
+ hspec-test/Ast/DeleteStmtSpec.hs view
@@ -0,0 +1,10 @@+module Ast.DeleteStmtSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.DeleteStmt+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @DeleteStmt+  itSatisfiesArbitrary @DeleteStmt
+ hspec-test/Ast/ExplicitRowSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ExplicitRowSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ExplicitRow+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ExplicitRow+  itSatisfiesArbitrary @ExplicitRow
+ hspec-test/Ast/ExprListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ExprListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ExprList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ExprList+  itSatisfiesArbitrary @ExprList
+ hspec-test/Ast/ExtractArgSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ExtractArgSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ExtractArg+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ExtractArg+  itSatisfiesArbitrary @ExtractArg
+ hspec-test/Ast/ExtractListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ExtractListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ExtractList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ExtractList+  itSatisfiesArbitrary @ExtractList
+ hspec-test/Ast/FconstSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FconstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Fconst+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Fconst+  itSatisfiesArbitrary @Fconst
+ hspec-test/Ast/ForLockingClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ForLockingClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ForLockingClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ForLockingClause+  itSatisfiesArbitrary @ForLockingClause
+ hspec-test/Ast/ForLockingItemSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ForLockingItemSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ForLockingItem+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ForLockingItem+  itSatisfiesArbitrary @ForLockingItem
+ hspec-test/Ast/ForLockingStrengthSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ForLockingStrengthSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ForLockingStrength+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ForLockingStrength+  itSatisfiesArbitrary @ForLockingStrength
+ hspec-test/Ast/FrameBoundSpec.hs view
@@ -0,0 +1,27 @@+module Ast.FrameBoundSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FrameBound+import PostgresqlSyntax.IsAst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @FrameBound+  itSatisfiesArbitrary @FrameBound+  describe "Postgres grammar conformance" $ do+    -- gram.y:17567 frame_bound. UNBOUNDED is an unreserved keyword, so+    -- @UNBOUNDED PRECEDING@ is ambiguous with @a_expr PRECEDING@ where+    -- the a_expr is a column named "unbounded"; gram.y:915 resolves it by+    -- giving UNBOUNDED lower precedence than PRECEDING, i.e. the keyword+    -- reading wins and the column reading needs quoting.+    it "frame_bound" $ do+      let render :: FrameBound -> Text+          render = toText mempty+      fmap render (parse @FrameBound mempty "unbounded preceding") `shouldBe` Right "UNBOUNDED PRECEDING"+      fmap render (parse @FrameBound mempty "unbounded following") `shouldBe` Right "UNBOUNDED FOLLOWING"+      fmap render (parse @FrameBound mempty "current row") `shouldBe` Right "CURRENT ROW"+      fmap render (parse @FrameBound mempty "1 preceding") `shouldBe` Right "1 PRECEDING"+      fmap render (parse @FrameBound mempty "a following") `shouldBe` Right "a FOLLOWING"+      fmap render (parse @FrameBound mempty "\"unbounded\" preceding") `shouldBe` Right "\"unbounded\" PRECEDING"
+ hspec-test/Ast/FrameClauseModeSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FrameClauseModeSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FrameClauseMode+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FrameClauseMode+  itSatisfiesArbitrary @FrameClauseMode
+ hspec-test/Ast/FrameClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FrameClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FrameClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FrameClause+  itSatisfiesArbitrary @FrameClause
+ hspec-test/Ast/FrameExtentSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FrameExtentSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FrameExtent+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FrameExtent+  itSatisfiesArbitrary @FrameExtent
+ hspec-test/Ast/FromClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FromClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FromClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FromClause+  itSatisfiesArbitrary @FromClause
+ hspec-test/Ast/FromListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FromListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FromList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FromList+  itSatisfiesArbitrary @FromList
+ hspec-test/Ast/FuncAliasClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncAliasClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncAliasClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncAliasClause+  itSatisfiesArbitrary @FuncAliasClause
+ hspec-test/Ast/FuncApplicationParamsSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncApplicationParamsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncApplicationParams+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncApplicationParams+  itSatisfiesArbitrary @FuncApplicationParams
+ hspec-test/Ast/FuncApplicationSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncApplicationSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncApplication+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncApplication+  itSatisfiesArbitrary @FuncApplication
+ hspec-test/Ast/FuncArgExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncArgExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncArgExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncArgExpr+  itSatisfiesArbitrary @FuncArgExpr
+ hspec-test/Ast/FuncConstArgsSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncConstArgsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncConstArgs+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncConstArgs+  itSatisfiesArbitrary @FuncConstArgs
+ hspec-test/Ast/FuncExprCommonSubexprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncExprCommonSubexprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncExprCommonSubexpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncExprCommonSubexpr+  itSatisfiesArbitrary @FuncExprCommonSubexpr
+ hspec-test/Ast/FuncExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncExpr+  itSatisfiesArbitrary @FuncExpr
+ hspec-test/Ast/FuncExprWindowlessSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncExprWindowlessSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncExprWindowless+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncExprWindowless+  itSatisfiesArbitrary @FuncExprWindowless
+ hspec-test/Ast/FuncNameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncNameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncName+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncName+  itSatisfiesArbitrary @FuncName
+ hspec-test/Ast/FuncTableSpec.hs view
@@ -0,0 +1,10 @@+module Ast.FuncTableSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.FuncTable+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @FuncTable+  itSatisfiesArbitrary @FuncTable
+ hspec-test/Ast/GenericTypeSpec.hs view
@@ -0,0 +1,10 @@+module Ast.GenericTypeSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.GenericType+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @GenericType+  itSatisfiesArbitrary @GenericType
+ hspec-test/Ast/GroupByItemSpec.hs view
@@ -0,0 +1,10 @@+module Ast.GroupByItemSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.GroupByItem+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @GroupByItem+  itSatisfiesArbitrary @GroupByItem
+ hspec-test/Ast/GroupClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.GroupClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.GroupClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @GroupClause+  itSatisfiesArbitrary @GroupClause
+ hspec-test/Ast/HavingClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.HavingClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.HavingClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @HavingClause+  itSatisfiesArbitrary @HavingClause
+ hspec-test/Ast/IconstSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IconstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Iconst+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Iconst+  itSatisfiesArbitrary @Iconst
+ hspec-test/Ast/IdentSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IdentSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Ident+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Ident+  itSatisfiesArbitrary @Ident
+ hspec-test/Ast/ImplicitRowSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ImplicitRowSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ImplicitRow+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ImplicitRow+  itSatisfiesArbitrary @ImplicitRow
+ hspec-test/Ast/InExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InExpr+  itSatisfiesArbitrary @InExpr
+ hspec-test/Ast/IndexElemDefSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IndexElemDefSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IndexElemDef+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @IndexElemDef+  itSatisfiesArbitrary @IndexElemDef
+ hspec-test/Ast/IndexElemSpec.hs view
@@ -0,0 +1,24 @@+module Ast.IndexElemSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IndexElem+import PostgresqlSyntax.IsAst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @IndexElem+  itSatisfiesArbitrary @IndexElem+  describe "Postgres grammar conformance" $ do+    -- gram.y:8558 index_elem: ColId index_elem_options, and gram.y:8596+    -- opt_nulls_order. index_elem_options' operator-class name+    -- (opt_qualified_name, gram.y:8525) is a bare ColId, so it is+    -- directly ambiguous with the unreserved NULLS that follows it.+    it "index_elem" $ do+      let render :: IndexElem -> Text+          render = toText mempty+      fmap render (parse @IndexElem mempty "a") `shouldBe` Right "a"+      fmap render (parse @IndexElem mempty "a nulls first") `shouldBe` Right "a NULLS FIRST"+      fmap render (parse @IndexElem mempty "a text_ops nulls first") `shouldBe` Right "a text_ops NULLS FIRST"+      fmap render (parse @IndexElem mempty "a collate \"C\" text_ops desc") `shouldBe` Right "a COLLATE \"C\" text_ops DESC"
+ hspec-test/Ast/IndexParamsSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IndexParamsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IndexParams+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @IndexParams+  itSatisfiesArbitrary @IndexParams
+ hspec-test/Ast/IndirectionElSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IndirectionElSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IndirectionEl+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @IndirectionEl+  itSatisfiesArbitrary @IndirectionEl
+ hspec-test/Ast/IndirectionSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IndirectionSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Indirection+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Indirection+  itSatisfiesArbitrary @Indirection
+ hspec-test/Ast/InsertColumnItemSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InsertColumnItemSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InsertColumnItem+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InsertColumnItem+  itSatisfiesArbitrary @InsertColumnItem
+ hspec-test/Ast/InsertColumnListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InsertColumnListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InsertColumnList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InsertColumnList+  itSatisfiesArbitrary @InsertColumnList
+ hspec-test/Ast/InsertRestSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InsertRestSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InsertRest+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InsertRest+  itSatisfiesArbitrary @InsertRest
+ hspec-test/Ast/InsertStmtSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InsertStmtSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InsertStmt+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InsertStmt+  itSatisfiesArbitrary @InsertStmt
+ hspec-test/Ast/InsertTargetSpec.hs view
@@ -0,0 +1,10 @@+module Ast.InsertTargetSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.InsertTarget+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @InsertTarget+  itSatisfiesArbitrary @InsertTarget
+ hspec-test/Ast/IntervalSecondSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IntervalSecondSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IntervalSecond+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @IntervalSecond+  itSatisfiesArbitrary @IntervalSecond
+ hspec-test/Ast/IntervalSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IntervalSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Interval+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Interval+  itSatisfiesArbitrary @Interval
+ hspec-test/Ast/IntoClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.IntoClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.IntoClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @IntoClause+  itSatisfiesArbitrary @IntoClause
+ hspec-test/Ast/JoinMethSpec.hs view
@@ -0,0 +1,10 @@+module Ast.JoinMethSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.JoinMeth+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @JoinMeth+  itSatisfiesArbitrary @JoinMeth
+ hspec-test/Ast/JoinQualSpec.hs view
@@ -0,0 +1,10 @@+module Ast.JoinQualSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.JoinQual+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @JoinQual+  itSatisfiesArbitrary @JoinQual
+ hspec-test/Ast/JoinTypeSpec.hs view
@@ -0,0 +1,10 @@+module Ast.JoinTypeSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.JoinType+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @JoinType+  itSatisfiesArbitrary @JoinType
+ hspec-test/Ast/JoinedTableSpec.hs view
@@ -0,0 +1,10 @@+module Ast.JoinedTableSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.JoinedTable+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @JoinedTable+  itSatisfiesArbitrary @JoinedTable
+ hspec-test/Ast/LimitClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.LimitClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.LimitClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @LimitClause+  itSatisfiesArbitrary @LimitClause
+ hspec-test/Ast/MathOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.MathOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.MathOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @MathOp+  itSatisfiesArbitrary @MathOp
+ hspec-test/Ast/NameListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.NameListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.NameList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @NameList+  itSatisfiesArbitrary @NameList
+ hspec-test/Ast/NullsOrderSpec.hs view
@@ -0,0 +1,10 @@+module Ast.NullsOrderSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.NullsOrder+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @NullsOrder+  itSatisfiesArbitrary @NullsOrder
+ hspec-test/Ast/NumericSpec.hs view
@@ -0,0 +1,10 @@+module Ast.NumericSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Numeric+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Numeric+  itSatisfiesArbitrary @Numeric
+ hspec-test/Ast/OffsetClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OffsetClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OffsetClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OffsetClause+  itSatisfiesArbitrary @OffsetClause
+ hspec-test/Ast/OnConflictDoSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OnConflictDoSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OnConflictDo+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OnConflictDo+  itSatisfiesArbitrary @OnConflictDo
+ hspec-test/Ast/OnConflictSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OnConflictSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OnConflict+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OnConflict+  itSatisfiesArbitrary @OnConflict
+ hspec-test/Ast/OpSpec.hs view
@@ -0,0 +1,11 @@+module Ast.OpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Op+import Test.Hspec+import Prelude hiding (Op)++spec :: Spec+spec = do+  itSatisfiesIsAst @Op+  itSatisfiesArbitrary @Op
+ hspec-test/Ast/OptOrdinalitySpec.hs view
@@ -0,0 +1,10 @@+module Ast.OptOrdinalitySpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OptOrdinality+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OptOrdinality+  itSatisfiesArbitrary @OptOrdinality
+ hspec-test/Ast/OptTempTableNameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OptTempTableNameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OptTempTableName+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OptTempTableName+  itSatisfiesArbitrary @OptTempTableName
+ hspec-test/Ast/OptVaryingSpec.hs view
@@ -0,0 +1,8 @@+module Ast.OptVaryingSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OptVarying+import Test.Hspec++spec :: Spec+spec = itSatisfiesArbitrary @OptVarying
+ hspec-test/Ast/OverClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OverClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OverClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OverClause+  itSatisfiesArbitrary @OverClause
+ hspec-test/Ast/OverlayListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OverlayListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OverlayList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OverlayList+  itSatisfiesArbitrary @OverlayList
+ hspec-test/Ast/OverrideKindSpec.hs view
@@ -0,0 +1,10 @@+module Ast.OverrideKindSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.OverrideKind+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @OverrideKind+  itSatisfiesArbitrary @OverrideKind
+ hspec-test/Ast/PositionListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.PositionListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.PositionList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @PositionList+  itSatisfiesArbitrary @PositionList
+ hspec-test/Ast/PreparableStmtSpec.hs view
@@ -0,0 +1,60 @@+module Ast.PreparableStmtSpec (spec) where++import qualified Data.Text as Text+import Helpers.Specs+import PostgresqlSyntax.Ast.PreparableStmt+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @PreparableStmt+  itSatisfiesArbitrary @PreparableStmt+  describe "Parsers" $ do+    itParses @PreparableStmt+      "select i :: int8 from 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"+    itParses @PreparableStmt "select * from items for update limit 1"+    itParses @PreparableStmt "select * from items limit 1 for update"+    itParses @PreparableStmt "select * from items for share limit 10"+    itParses @PreparableStmt "select * from items for no key update limit 1"+    itParses @PreparableStmt "select * from items for key share limit 1"+    itParses @PreparableStmt "select * from items for update of items nowait limit 1"+    itParses @PreparableStmt "select * from items for update skip locked limit 1"+    itParses @PreparableStmt "select * from items order by id for update limit 1"+    itParses @PreparableStmt "select * from items for update offset 5 limit 10"+  describe "Nesting depth" $ do+    itParsesWithin @PreparableStmt 5 ("select " <> Text.replicate 50 "(" <> "a + b" <> Text.replicate 50 ")")+  describe "Error reporting" $ do+    itReportsError @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"+      "(21,\"offset=21:\\nunexpected 'a'\\nexpecting end of input or white space\\n\")"+    itReportsError @PreparableStmt+      "select i :: int8 from auth.user as u\n\+      \WHERE u.id IS NO NULL && TRUE"+      "(51,\"offset=51:\\nexpecting white space\\n\")"+  describe "SourcePos error reporting" $ do+    itReportsSourcePosError @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"+      "1:22 unexpected 'a'\nexpecting end of input or white space\n"+    itReportsSourcePosError @PreparableStmt+      "select i :: int8 from auth.user as u\n\+      \WHERE u.id IS NO NULL && TRUE"+      "2:15 expecting white space\n"+    itReportsSourcePosError @PreparableStmt+      "SLECT id FROM qsdqsd"+      "1:1 unexpected 'S'\nexpecting '(' or white space\n"+    itReportsSourcePosError @PreparableStmt+      "SELECT id FROM as"+      "1:18 Reserved keyword \"as\" used as an identifier. If that's what you intend, you have to wrap it in double quotes.\n"
+ hspec-test/Ast/QualAllOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.QualAllOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.QualAllOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @QualAllOp+  itSatisfiesArbitrary @QualAllOp
+ hspec-test/Ast/QualOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.QualOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.QualOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @QualOp+  itSatisfiesArbitrary @QualOp
+ hspec-test/Ast/QualifiedNameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.QualifiedNameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.QualifiedName+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @QualifiedName+  itSatisfiesArbitrary @QualifiedName
+ hspec-test/Ast/RelationExprOptAliasSpec.hs view
@@ -0,0 +1,10 @@+module Ast.RelationExprOptAliasSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.RelationExprOptAlias+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @RelationExprOptAlias+  itSatisfiesArbitrary @RelationExprOptAlias
+ hspec-test/Ast/RelationExprSpec.hs view
@@ -0,0 +1,10 @@+module Ast.RelationExprSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.RelationExpr+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @RelationExpr+  itSatisfiesArbitrary @RelationExpr
+ hspec-test/Ast/ReturningClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ReturningClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ReturningClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ReturningClause+  itSatisfiesArbitrary @ReturningClause
+ hspec-test/Ast/RowSpec.hs view
@@ -0,0 +1,10 @@+module Ast.RowSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Row+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Row+  itSatisfiesArbitrary @Row
+ hspec-test/Ast/RowsfromItemSpec.hs view
@@ -0,0 +1,10 @@+module Ast.RowsfromItemSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.RowsfromItem+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @RowsfromItem+  itSatisfiesArbitrary @RowsfromItem
+ hspec-test/Ast/RowsfromListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.RowsfromListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.RowsfromList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @RowsfromList+  itSatisfiesArbitrary @RowsfromList
+ hspec-test/Ast/SconstSpec.hs view
@@ -0,0 +1,15 @@+module Ast.SconstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Sconst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @Sconst+  itSatisfiesArbitrary @Sconst+  describe "Parsers" $ do+    itParses @Sconst "'it''s good'"+    itParses @Sconst "$$it's good$$"+    itParses @Sconst "$x$it's good$x$"
+ hspec-test/Ast/SelectBinOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectBinOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectBinOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectBinOp+  itSatisfiesArbitrary @SelectBinOp
+ hspec-test/Ast/SelectClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectClause+  itSatisfiesArbitrary @SelectClause
+ hspec-test/Ast/SelectFetchFirstValueSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectFetchFirstValueSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectFetchFirstValue+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectFetchFirstValue+  itSatisfiesArbitrary @SelectFetchFirstValue
+ hspec-test/Ast/SelectLimitSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectLimitSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectLimit+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectLimit+  itSatisfiesArbitrary @SelectLimit
+ hspec-test/Ast/SelectLimitValueSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectLimitValueSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectLimitValue+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectLimitValue+  itSatisfiesArbitrary @SelectLimitValue
+ hspec-test/Ast/SelectNoParensSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectNoParensSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectNoParens+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectNoParens+  itSatisfiesArbitrary @SelectNoParens
+ hspec-test/Ast/SelectStmtSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SelectStmtSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectStmt+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectStmt+  itSatisfiesArbitrary @SelectStmt
+ hspec-test/Ast/SelectWithParensSpec.hs view
@@ -0,0 +1,18 @@+module Ast.SelectWithParensSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SelectNoParens+import PostgresqlSyntax.Ast.SelectWithParens+import PostgresqlSyntax.IsAst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @SelectWithParens+  itSatisfiesArbitrary @SelectWithParens+  describe "Nesting depth" $ do+    -- The parenthesised sub-select has two possible representations.+    it "redundant parens around a sub-select are canonicalised"+      $ parse @SelectWithParens mempty "((select 1))"+      `shouldBe` (WithParensSelectWithParens . NoParensSelectWithParens <$> parse @SelectNoParens mempty "select 1")
+ hspec-test/Ast/SetClauseListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SetClauseListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SetClauseList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SetClauseList+  itSatisfiesArbitrary @SetClauseList
+ hspec-test/Ast/SetClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SetClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SetClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SetClause+  itSatisfiesArbitrary @SetClause
+ hspec-test/Ast/SetTargetListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SetTargetListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SetTargetList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SetTargetList+  itSatisfiesArbitrary @SetTargetList
+ hspec-test/Ast/SetTargetSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SetTargetSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SetTarget+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SetTarget+  itSatisfiesArbitrary @SetTarget
+ hspec-test/Ast/SimpleSelectSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SimpleSelectSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SimpleSelect+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SimpleSelect+  itSatisfiesArbitrary @SimpleSelect
+ hspec-test/Ast/SimpleTypenameSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SimpleTypenameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SimpleTypename+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SimpleTypename+  itSatisfiesArbitrary @SimpleTypename
+ hspec-test/Ast/SortBySpec.hs view
@@ -0,0 +1,24 @@+module Ast.SortBySpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SortBy+import PostgresqlSyntax.IsAst+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @SortBy+  itSatisfiesArbitrary @SortBy+  describe "Postgres grammar conformance" $ do+    it "sortby" $ do+      let render :: SortBy -> Text+          render = toText mempty+      fmap render (parse @SortBy mempty "a") `shouldBe` Right "a"+      fmap render (parse @SortBy mempty "a asc") `shouldBe` Right "a ASC"+      fmap render (parse @SortBy mempty "a desc nulls last") `shouldBe` Right "a DESC NULLS LAST"+      fmap render (parse @SortBy mempty "a nulls first") `shouldBe` Right "a NULLS FIRST"+      fmap render (parse @SortBy mempty "a using > nulls last") `shouldBe` Right "a USING > NULLS LAST"+      case parse @SortBy mempty "nulls" of+        Left _ -> pure ()+        Right _ -> expectationFailure "expected a parse failure for bare \"nulls\""
+ hspec-test/Ast/SortClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SortClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SortClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SortClause+  itSatisfiesArbitrary @SortClause
+ hspec-test/Ast/SubTypeSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SubTypeSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SubType+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SubType+  itSatisfiesArbitrary @SubType
+ hspec-test/Ast/SubqueryOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SubqueryOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SubqueryOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SubqueryOp+  itSatisfiesArbitrary @SubqueryOp
+ hspec-test/Ast/SubstrListFromForSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SubstrListFromForSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SubstrListFromFor+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SubstrListFromFor+  itSatisfiesArbitrary @SubstrListFromFor
+ hspec-test/Ast/SubstrListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SubstrListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SubstrList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SubstrList+  itSatisfiesArbitrary @SubstrList
+ hspec-test/Ast/SymbolicExprBinOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.SymbolicExprBinOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.SymbolicExprBinOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @SymbolicExprBinOp+  itSatisfiesArbitrary @SymbolicExprBinOp
+ hspec-test/Ast/TableFuncElementListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TableFuncElementListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TableFuncElementList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TableFuncElementList+  itSatisfiesArbitrary @TableFuncElementList
+ hspec-test/Ast/TableFuncElementSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TableFuncElementSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TableFuncElement+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TableFuncElement+  itSatisfiesArbitrary @TableFuncElement
+ hspec-test/Ast/TableRefSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TableRefSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TableRef+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TableRef+  itSatisfiesArbitrary @TableRef
+ hspec-test/Ast/TablesampleClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TablesampleClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TablesampleClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TablesampleClause+  itSatisfiesArbitrary @TablesampleClause
+ hspec-test/Ast/TargetElSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TargetElSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TargetEl+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TargetEl+  itSatisfiesArbitrary @TargetEl
+ hspec-test/Ast/TargetListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TargetListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TargetList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TargetList+  itSatisfiesArbitrary @TargetList
+ hspec-test/Ast/TargetingSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TargetingSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Targeting+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Targeting+  itSatisfiesArbitrary @Targeting
+ hspec-test/Ast/TimezoneSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TimezoneSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Timezone+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Timezone+  itSatisfiesArbitrary @Timezone
+ hspec-test/Ast/TrimListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TrimListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TrimList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TrimList+  itSatisfiesArbitrary @TrimList
+ hspec-test/Ast/TrimModifierSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TrimModifierSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TrimModifier+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TrimModifier+  itSatisfiesArbitrary @TrimModifier
+ hspec-test/Ast/TypeListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.TypeListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TypeList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @TypeList+  itSatisfiesArbitrary @TypeList
+ hspec-test/Ast/TypenameArrayDimensionsSpec.hs view
@@ -0,0 +1,8 @@+module Ast.TypenameArrayDimensionsSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.TypenameArrayDimensions+import Test.Hspec++spec :: Spec+spec = itSatisfiesArbitrary @TypenameArrayDimensions
+ hspec-test/Ast/TypenameSpec.hs view
@@ -0,0 +1,46 @@+module Ast.TypenameSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Typename+import PostgresqlSyntax.Settings (nullabilityMarkers)+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @Typename+  itSatisfiesArbitrary @Typename+  describe "Parsers" $ do+    itParses @Typename "int4"+    itParses @Typename "int4[][]"+    itParses @Typename "aa array"+    itParses @Typename "DOUBLE PRECISION"+    itParses @Typename "bool"+    itParses @Typename "int2"+    itParses @Typename "int4"+    itParses @Typename "int8"+    itParses @Typename "float4"+    itParses @Typename "float8"+    itParses @Typename "numeric"+    itParses @Typename "char"+    itParses @Typename "text"+    itParses @Typename "bytea"+    itParses @Typename "date"+    itParses @Typename "timestamp"+    itParses @Typename "timestamptz"+    itParses @Typename "time"+    itParses @Typename "timetz"+    itParses @Typename "interval"+    itParses @Typename "uuid"+    itParses @Typename "inet"+    itParses @Typename "json"+    itParses @Typename "jsonb"+  describe "extended" $ do+    itParsesWith @Typename (nullabilityMarkers True) "text?"+    itParsesWith @Typename (nullabilityMarkers True) "text[]?"+    itParsesWith @Typename (nullabilityMarkers True) "text?[]?"+    itParsesWith @Typename (nullabilityMarkers True) "text?[]"+    itRejectsWith @Typename mempty "text?"+    itRejectsWith @Typename mempty "text[]?"+    itRejectsWith @Typename mempty "text?[]?"+    itRejectsWith @Typename mempty "text?[]"
+ hspec-test/Ast/UpdateStmtSpec.hs view
@@ -0,0 +1,10 @@+module Ast.UpdateStmtSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.UpdateStmt+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @UpdateStmt+  itSatisfiesArbitrary @UpdateStmt
+ hspec-test/Ast/UsingClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.UsingClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.UsingClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @UsingClause+  itSatisfiesArbitrary @UsingClause
+ hspec-test/Ast/ValuesClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.ValuesClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.ValuesClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @ValuesClause+  itSatisfiesArbitrary @ValuesClause
+ hspec-test/Ast/VerbalExprBinOpSpec.hs view
@@ -0,0 +1,10 @@+module Ast.VerbalExprBinOpSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.VerbalExprBinOp+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @VerbalExprBinOp+  itSatisfiesArbitrary @VerbalExprBinOp
+ hspec-test/Ast/WhenClauseListSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WhenClauseListSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WhenClauseList+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WhenClauseList+  itSatisfiesArbitrary @WhenClauseList
+ hspec-test/Ast/WhenClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WhenClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WhenClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WhenClause+  itSatisfiesArbitrary @WhenClause
+ hspec-test/Ast/WhereClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WhereClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WhereClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WhereClause+  itSatisfiesArbitrary @WhereClause
+ hspec-test/Ast/WhereOrCurrentClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WhereOrCurrentClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WhereOrCurrentClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WhereOrCurrentClause+  itSatisfiesArbitrary @WhereOrCurrentClause
+ hspec-test/Ast/WindowClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WindowClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WindowClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WindowClause+  itSatisfiesArbitrary @WindowClause
+ hspec-test/Ast/WindowDefinitionSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WindowDefinitionSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WindowDefinition+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WindowDefinition+  itSatisfiesArbitrary @WindowDefinition
+ hspec-test/Ast/WindowExclusionClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WindowExclusionClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WindowExclusionClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WindowExclusionClause+  itSatisfiesArbitrary @WindowExclusionClause
+ hspec-test/Ast/WindowSpecificationSpec.hs view
@@ -0,0 +1,20 @@+module Ast.WindowSpecificationSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WindowSpecification+import Test.Hspec+import Prelude++spec :: Spec+spec = do+  itSatisfiesIsAst @WindowSpecification+  itSatisfiesArbitrary @WindowSpecification+  describe "Postgres grammar conformance" $ do+    -- gram.y:17428 window_specification: the sort clause and the+    -- partition clause are both followed by opt_frame_clause, whose+    -- leading keywords (RANGE/ROWS/GROUPS, kwlist.h:375,408,201) are+    -- unreserved and therefore also legal ColIds.+    itParses @WindowSpecification "(order by a rows unbounded preceding)"+    itParses @WindowSpecification "(order by a range unbounded preceding)"+    itParses @WindowSpecification "(partition by a groups unbounded preceding)"+    itParses @WindowSpecification "(partition by a order by b rows 1 preceding)"
+ hspec-test/Ast/WithClauseSpec.hs view
@@ -0,0 +1,10 @@+module Ast.WithClauseSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.WithClause+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @WithClause+  itSatisfiesArbitrary @WithClause
+ hspec-test/Ast/XconstSpec.hs view
@@ -0,0 +1,10 @@+module Ast.XconstSpec (spec) where++import Helpers.Specs+import PostgresqlSyntax.Ast.Xconst+import Test.Hspec++spec :: Spec+spec = do+  itSatisfiesIsAst @Xconst+  itSatisfiesArbitrary @Xconst
+ hspec-test/Helpers/Expectations.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE AllowAmbiguousTypes #-}++module Helpers.Expectations+  ( parsesTo,+    rejects,+    reportsError,+    reportsSourcePosError,+    parsesWithin,+    parsesToWith,+    rejectsWith,+  )+where++import qualified Data.List.NonEmpty as NonEmpty+import qualified Data.Text as Text+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Settings (Settings)+import Test.Hspec+import Text.Megaparsec.Pos (sourcePosPretty)+import Prelude++parsesTo :: forall a. (HasCallStack, IsAst a) => Text -> Expectation+parsesTo input =+  case parse @a mempty input of+    Left err -> expectationFailure (Text.unpack (err <> "\ninput: " <> input))+    Right _ -> pure ()++rejects :: forall a. (HasCallStack, IsAst a, Show a) => Text -> Expectation+rejects input =+  case parse @a mempty input of+    Left _ -> pure ()+    Right a ->+      expectationFailure+        ("expected a parse failure\ninput: " <> Text.unpack input <> "\nparsed: " <> show a)++reportsError :: forall a. (HasCallStack, IsAst a) => Text -> String -> Expectation+reportsError input expected =+  case parseWithPosError @a mempty input of+    Left err -> show (NonEmpty.head err) `shouldBe` expected+    Right _ -> expectationFailure "expected a parse error, but it succeeded"++-- | Like 'reportsError' but checks 'parseWithSourcePosError''s+-- 'Text.Megaparsec.SourcePos'-based errors instead.+reportsSourcePosError :: forall a. (HasCallStack, IsAst a) => Text -> String -> Expectation+reportsSourcePosError input expected =+  case parseWithSourcePosError @a mempty input of+    Left err ->+      let (pos, msg) = NonEmpty.head err+       in (Text.unpack (Text.pack (sourcePosPretty pos) <> " " <> msg)) `shouldBe` expected+    Right _ -> expectationFailure "expected a parse error, but it succeeded"++parsesWithin :: forall a. (HasCallStack, IsAst a) => Int -> Text -> Expectation+parsesWithin seconds input = do+  result <-+    timeout (seconds * 1000000)+      $ case parse @a mempty input of+        Left err -> expectationFailure (Text.unpack (err <> "\ninput: " <> input))+        Right _ -> pure ()+  case result of+    Nothing -> expectationFailure ("Did not finish parsing within " <> show seconds <> "s")+    Just () -> pure ()++-- | Like 'parsesTo' but with a non-default 'Settings'.+parsesToWith :: forall a. (HasCallStack, IsAst a) => Settings -> Text -> Expectation+parsesToWith settings input =+  case parse @a settings input of+    Left err -> expectationFailure (Text.unpack (err <> "\ninput: " <> input))+    Right _ -> pure ()++-- | Like 'rejects' but with a non-default 'Settings'.+rejectsWith :: forall a. (HasCallStack, IsAst a, Show a) => Settings -> Text -> Expectation+rejectsWith settings input =+  case parse @a settings input of+    Left _ -> pure ()+    Right a ->+      expectationFailure+        ("expected a parse failure\ninput: " <> Text.unpack input <> "\nparsed: " <> show a)
+ hspec-test/Helpers/Specs.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE AllowAmbiguousTypes #-}++module Helpers.Specs+  ( itSatisfiesIsAst,+    itSatisfiesArbitrary,+    itParses,+    itRejects,+    itReportsError,+    itReportsSourcePosError,+    itParsesWithin,++    -- * Settings-aware variants+    itParsesWith,+    itRejectsWith,+  )+where++import qualified Data.Text as Text+import qualified Helpers.Expectations as Expectations+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Settings (Settings)+import Test.Hspec+import Test.Hspec.QuickCheck (prop)+import Test.QuickCheck (counterexample, (===))+import qualified Test.QuickCheck as Qc+import Prelude++itSatisfiesIsAst :: forall a. (IsAst a, Eq a, Show a, Qc.Arbitrary a) => Spec+itSatisfiesIsAst =+  describe "IsAst" $ do+    prop "Roundtrips" $ \(a :: a) ->+      let sql = toText mempty a+       in case parse mempty sql of+            Left err ->+              counterexample ("rendered: " <> Text.unpack sql <> "\nparse failed: " <> Text.unpack err) False+            Right a' ->+              counterexample+                ("rendered: " <> Text.unpack sql <> "\nrestored: " <> Text.unpack (toText mempty a'))+                (a' === a)++itSatisfiesArbitrary :: forall a. (IsAst a, Show a, Qc.Arbitrary a) => Spec+itSatisfiesArbitrary =+  describe "Arbitrary" $ do+    prop "Terminates at size 0" terminatesAtZero+    prop "Grows boundedly" growsBounded+  where+    terminatesAtZero =+      Qc.forAll (Qc.resize 0 (Qc.arbitrary @a)) $ \x ->+        let sql = toText mempty x+            len = Text.length sql+         in Qc.counterexample+              ("rendered " <> show len <> " chars at size 0 (max " <> show zeroSizeMaxLen <> ")" <> "\n" <> Text.unpack sql)+              (len <= zeroSizeMaxLen)+      where+        zeroSizeMaxLen = 500 :: Int++    growsBounded =+      Qc.forAll (Qc.resize maxGenSize (Qc.arbitrary @a)) $ \x ->+        let sql = toText mempty x+            len = Text.length sql+         in Qc.counterexample+              ("rendered " <> show len <> " chars at size " <> show maxGenSize <> " (max " <> show maxGenSizeMaxLen <> ")")+              (len <= maxGenSizeMaxLen)+      where+        maxGenSize = 100 :: Int+        maxGenSizeMaxLen = 1000000 :: Int++itParses :: forall a. (HasCallStack, IsAst a) => Text -> Spec+itParses sql =+  describe (Text.unpack sql) $ do+    it "Parses" (Expectations.parsesTo @a sql)++itRejects :: forall a. (HasCallStack, IsAst a, Show a) => Text -> Spec+itRejects sql =+  describe (Text.unpack sql) $ do+    it "Rejects" (Expectations.rejects @a sql)++itReportsError :: forall a. (HasCallStack, IsAst a) => Text -> String -> Spec+itReportsError sql expected =+  describe (Text.unpack sql) $ do+    it ("Reports error: " <> expected) (Expectations.reportsError @a sql expected)++-- | Like 'itReportsError' but checks 'PostgresqlSyntax.IsAst.parseWithSourcePosError''s+-- 'Text.Megaparsec.SourcePos'-based errors instead.+itReportsSourcePosError :: forall a. (HasCallStack, IsAst a) => Text -> String -> Spec+itReportsSourcePosError sql expected =+  describe (Text.unpack sql) $ do+    it ("Reports error: " <> expected) (Expectations.reportsSourcePosError @a sql expected)++itParsesWithin :: forall a. (HasCallStack, IsAst a) => Int -> Text -> Spec+itParsesWithin seconds sql =+  describe (Text.unpack sql) $ do+    it ("Parses within " <> show seconds <> " seconds") (Expectations.parsesWithin @a seconds sql)++-- | Wraps 'Expectations.parsesToWith' as a standalone 'Spec'.+itParsesWith :: forall a. (HasCallStack, IsAst a) => Settings -> Text -> Spec+itParsesWith settings sql =+  describe (Text.unpack sql) $ do+    it "Parses" (Expectations.parsesToWith @a settings sql)++-- | Wraps 'Expectations.rejectsWith' as a standalone 'Spec'.+itRejectsWith :: forall a. (HasCallStack, IsAst a, Show a) => Settings -> Text -> Spec+itRejectsWith settings sql =+  describe (Text.unpack sql) $ do+    it "Rejects" (Expectations.rejectsWith @a settings sql)
+ hspec-test/Main.hs view
@@ -0,0 +1,8 @@+module Main (main) where++import qualified Spec+import Test.Hspec+import Prelude++main :: IO ()+main = hspec $ parallel Spec.spec
+ hspec-test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --module-name=Spec #-}
+ library-internal/PostgresqlSyntax/Ast.hs view
@@ -0,0 +1,382 @@+-- |+-- Names for nodes mostly resemble the according definitions in the @gram.y@+-- original Postgres parser file, except for the cases where we can optimize on that.+--+-- For reasoning see the docs of the parsing module of this project.+module PostgresqlSyntax.Ast+  ( -- * Nodes+    AExpr (..),+    AExprReversableOp (..),+    AexprConst (..),+    AliasClause (..),+    AllOp (..),+    AnyName (..),+    AnyOperator (..),+    ArrayBounds (..),+    ArrayExpr (..),+    ArrayExprList (..),+    AscDesc (..),+    Attrs (..),+    BExpr (..),+    BExprIsOp (..),+    Bconst (..),+    Bit (..),+    CExpr (..),+    CallStmt (..),+    CaseExpr (..),+    Character (..),+    Columnref (..),+    CommonTableExpr (..),+    ConfExpr (..),+    ConstCharacter (..),+    ConstDatetime (..),+    ConstTypename (..),+    DeleteStmt (..),+    ExplicitRow (..),+    ExprList (..),+    ExtractArg (..),+    ExtractList (..),+    Fconst (..),+    ForLockingClause (..),+    ForLockingItem (..),+    ForLockingStrength (..),+    FrameBound (..),+    FrameClause (..),+    FrameClauseMode (..),+    FrameExtent (..),+    FromClause (..),+    FromList (..),+    FuncAliasClause (..),+    FuncApplication (..),+    FuncApplicationParams (..),+    FuncArgExpr (..),+    FuncConstArgs (..),+    FuncExpr (..),+    FuncExprCommonSubexpr (..),+    FuncExprWindowless (..),+    FuncName (..),+    FuncTable (..),+    GenericType (..),+    GroupByItem (..),+    GroupClause (..),+    HavingClause (..),+    Iconst (..),+    Ident (..),+    ImplicitRow (..),+    InExpr (..),+    IndexElem (..),+    IndexElemDef (..),+    IndexParams (..),+    Indirection (..),+    IndirectionEl (..),+    InsertColumnItem (..),+    InsertColumnList (..),+    InsertRest (..),+    InsertStmt (..),+    InsertTarget (..),+    Interval (..),+    IntervalSecond (..),+    IntoClause (..),+    JoinMeth (..),+    JoinQual (..),+    JoinType (..),+    JoinedTable (..),+    LimitClause (..),+    MathOp (..),+    NameList (..),+    NullsOrder (..),+    Numeric (..),+    OffsetClause (..),+    OnConflict (..),+    OnConflictDo (..),+    Op (..),+    OptOrdinality (..),+    OptTempTableName (..),+    OptVarying (..),+    OverClause (..),+    OverlayList (..),+    OverrideKind (..),+    PositionList (..),+    PreparableStmt (..),+    QualAllOp (..),+    QualOp (..),+    QualifiedName (..),+    RelationExpr (..),+    RelationExprOptAlias (..),+    ReturningClause (..),+    Row (..),+    RowsfromItem (..),+    RowsfromList (..),+    Sconst (..),+    SelectBinOp (..),+    SelectClause (..),+    SelectFetchFirstValue (..),+    SelectLimit (..),+    SelectLimitValue (..),+    SelectNoParens (..),+    SelectStmt (..),+    SelectWithParens (..),+    SetClause (..),+    SetClauseList (..),+    SetTarget (..),+    SetTargetList (..),+    SimpleSelect (..),+    SimpleTypename (..),+    SortBy (..),+    SortClause (..),+    SubType (..),+    SubqueryOp (..),+    SubstrList (..),+    SubstrListFromFor (..),+    SymbolicExprBinOp (..),+    TableFuncElement (..),+    TableFuncElementList (..),+    TableRef (..),+    TablesampleClause (..),+    TargetEl (..),+    TargetList (..),+    Targeting (..),+    Timezone (..),+    TrimList (..),+    TrimModifier (..),+    TypeList (..),+    Typename (..),+    TypenameArrayDimensions (..),+    UpdateStmt (..),+    UsingClause (..),+    ValuesClause (..),+    VerbalExprBinOp (..),+    WhenClause (..),+    WhenClauseList (..),+    WhereClause (..),+    WhereOrCurrentClause (..),+    WindowClause (..),+    WindowDefinition (..),+    WindowExclusionClause (..),+    WindowSpecification (..),+    WithClause (..),+    Xconst (..),++    -- * Bare aliases+    ExistingWindowName,+    PartitionClause,+    RepeatableClause,+    ColDefList,+    CollateClause,+    WithinGroupClause,+    FilterClause,+    OverlayPlacing,+    SubstrFrom,+    SubstrFor,+    CaseArg,+    CaseDefault,+    ConstBit,+    ColId,+    ColLabel,+    Name,+    CursorName,+    AttrName,+    TypeModifiers,+    Collate,+    Class,+    TypeFunctionName,+  )+where++import PostgresqlSyntax.Ast.AExpr+import PostgresqlSyntax.Ast.AExprReversableOp+import PostgresqlSyntax.Ast.AexprConst+import PostgresqlSyntax.Ast.AliasClause+import PostgresqlSyntax.Ast.AllOp+import PostgresqlSyntax.Ast.AnyName+import PostgresqlSyntax.Ast.AnyOperator+import PostgresqlSyntax.Ast.ArrayBounds+import PostgresqlSyntax.Ast.ArrayExpr+import PostgresqlSyntax.Ast.ArrayExprList+import PostgresqlSyntax.Ast.AscDesc+import PostgresqlSyntax.Ast.Attrs+import PostgresqlSyntax.Ast.BExpr+import PostgresqlSyntax.Ast.BExprIsOp+import PostgresqlSyntax.Ast.Bconst+import PostgresqlSyntax.Ast.Bit+import PostgresqlSyntax.Ast.CExpr+import PostgresqlSyntax.Ast.CallStmt+import PostgresqlSyntax.Ast.CaseExpr+import PostgresqlSyntax.Ast.Character+import PostgresqlSyntax.Ast.Columnref+import PostgresqlSyntax.Ast.CommonTableExpr+import PostgresqlSyntax.Ast.ConfExpr+import PostgresqlSyntax.Ast.ConstCharacter+import PostgresqlSyntax.Ast.ConstDatetime+import PostgresqlSyntax.Ast.ConstTypename+import PostgresqlSyntax.Ast.DeleteStmt+import PostgresqlSyntax.Ast.ExplicitRow+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.ExtractArg+import PostgresqlSyntax.Ast.ExtractList+import PostgresqlSyntax.Ast.Fconst+import PostgresqlSyntax.Ast.ForLockingClause+import PostgresqlSyntax.Ast.ForLockingItem+import PostgresqlSyntax.Ast.ForLockingStrength+import PostgresqlSyntax.Ast.FrameBound+import PostgresqlSyntax.Ast.FrameClause+import PostgresqlSyntax.Ast.FrameClauseMode+import PostgresqlSyntax.Ast.FrameExtent+import PostgresqlSyntax.Ast.FromClause+import PostgresqlSyntax.Ast.FromList+import PostgresqlSyntax.Ast.FuncAliasClause+import PostgresqlSyntax.Ast.FuncApplication+import PostgresqlSyntax.Ast.FuncApplicationParams+import PostgresqlSyntax.Ast.FuncArgExpr+import PostgresqlSyntax.Ast.FuncConstArgs+import PostgresqlSyntax.Ast.FuncExpr+import PostgresqlSyntax.Ast.FuncExprCommonSubexpr+import PostgresqlSyntax.Ast.FuncExprWindowless+import PostgresqlSyntax.Ast.FuncName+import PostgresqlSyntax.Ast.FuncTable+import PostgresqlSyntax.Ast.GenericType+import PostgresqlSyntax.Ast.GroupByItem+import PostgresqlSyntax.Ast.GroupClause+import PostgresqlSyntax.Ast.HavingClause+import PostgresqlSyntax.Ast.Iconst+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.ImplicitRow+import PostgresqlSyntax.Ast.InExpr+import PostgresqlSyntax.Ast.IndexElem+import PostgresqlSyntax.Ast.IndexElemDef+import PostgresqlSyntax.Ast.IndexParams+import PostgresqlSyntax.Ast.Indirection+import PostgresqlSyntax.Ast.IndirectionEl+import PostgresqlSyntax.Ast.InsertColumnItem+import PostgresqlSyntax.Ast.InsertColumnList+import PostgresqlSyntax.Ast.InsertRest+import PostgresqlSyntax.Ast.InsertStmt+import PostgresqlSyntax.Ast.InsertTarget+import PostgresqlSyntax.Ast.Interval+import PostgresqlSyntax.Ast.IntervalSecond+import PostgresqlSyntax.Ast.IntoClause+import PostgresqlSyntax.Ast.JoinMeth+import PostgresqlSyntax.Ast.JoinQual+import PostgresqlSyntax.Ast.JoinType+import PostgresqlSyntax.Ast.JoinedTable+import PostgresqlSyntax.Ast.LimitClause+import PostgresqlSyntax.Ast.MathOp+import PostgresqlSyntax.Ast.NameList+import PostgresqlSyntax.Ast.NullsOrder+import PostgresqlSyntax.Ast.Numeric+import PostgresqlSyntax.Ast.OffsetClause+import PostgresqlSyntax.Ast.OnConflict+import PostgresqlSyntax.Ast.OnConflictDo+import PostgresqlSyntax.Ast.Op+import PostgresqlSyntax.Ast.OptOrdinality+import PostgresqlSyntax.Ast.OptTempTableName+import PostgresqlSyntax.Ast.OptVarying+import PostgresqlSyntax.Ast.OverClause+import PostgresqlSyntax.Ast.OverlayList+import PostgresqlSyntax.Ast.OverrideKind+import PostgresqlSyntax.Ast.PositionList+import PostgresqlSyntax.Ast.PreparableStmt+import PostgresqlSyntax.Ast.QualAllOp+import PostgresqlSyntax.Ast.QualOp+import PostgresqlSyntax.Ast.QualifiedName+import PostgresqlSyntax.Ast.RelationExpr+import PostgresqlSyntax.Ast.RelationExprOptAlias+import PostgresqlSyntax.Ast.ReturningClause+import PostgresqlSyntax.Ast.Row+import PostgresqlSyntax.Ast.RowsfromItem+import PostgresqlSyntax.Ast.RowsfromList+import PostgresqlSyntax.Ast.Sconst+import PostgresqlSyntax.Ast.SelectBinOp+import PostgresqlSyntax.Ast.SelectClause+import PostgresqlSyntax.Ast.SelectFetchFirstValue+import PostgresqlSyntax.Ast.SelectLimit+import PostgresqlSyntax.Ast.SelectLimitValue+import PostgresqlSyntax.Ast.SelectNoParens+import PostgresqlSyntax.Ast.SelectStmt+import PostgresqlSyntax.Ast.SelectWithParens+import PostgresqlSyntax.Ast.SetClause+import PostgresqlSyntax.Ast.SetClauseList+import PostgresqlSyntax.Ast.SetTarget+import PostgresqlSyntax.Ast.SetTargetList+import PostgresqlSyntax.Ast.SimpleSelect+import PostgresqlSyntax.Ast.SimpleTypename+import PostgresqlSyntax.Ast.SortBy+import PostgresqlSyntax.Ast.SortClause+import PostgresqlSyntax.Ast.SubType+import PostgresqlSyntax.Ast.SubqueryOp+import PostgresqlSyntax.Ast.SubstrList+import PostgresqlSyntax.Ast.SubstrListFromFor+import PostgresqlSyntax.Ast.SymbolicExprBinOp+import PostgresqlSyntax.Ast.TableFuncElement+import PostgresqlSyntax.Ast.TableFuncElementList+import PostgresqlSyntax.Ast.TableRef+import PostgresqlSyntax.Ast.TablesampleClause+import PostgresqlSyntax.Ast.TargetEl+import PostgresqlSyntax.Ast.TargetList+import PostgresqlSyntax.Ast.Targeting+import PostgresqlSyntax.Ast.Timezone+import PostgresqlSyntax.Ast.TrimList+import PostgresqlSyntax.Ast.TrimModifier+import PostgresqlSyntax.Ast.TypeList+import PostgresqlSyntax.Ast.Typename+import PostgresqlSyntax.Ast.TypenameArrayDimensions+import PostgresqlSyntax.Ast.UpdateStmt+import PostgresqlSyntax.Ast.UsingClause+import PostgresqlSyntax.Ast.ValuesClause+import PostgresqlSyntax.Ast.VerbalExprBinOp+import PostgresqlSyntax.Ast.WhenClause+import PostgresqlSyntax.Ast.WhenClauseList+import PostgresqlSyntax.Ast.WhereClause+import PostgresqlSyntax.Ast.WhereOrCurrentClause+import PostgresqlSyntax.Ast.WindowClause+import PostgresqlSyntax.Ast.WindowDefinition+import PostgresqlSyntax.Ast.WindowExclusionClause+import PostgresqlSyntax.Ast.WindowSpecification+import PostgresqlSyntax.Ast.WithClause+import PostgresqlSyntax.Ast.Xconst++-- * Bare aliases++type ExistingWindowName = ColId++type PartitionClause = ExprList++type RepeatableClause = AExpr++type ColDefList = TableFuncElementList++type CollateClause = AnyName++type WithinGroupClause = SortClause++type FilterClause = AExpr++type OverlayPlacing = AExpr++type SubstrFrom = AExpr++type SubstrFor = AExpr++type CaseArg = AExpr++type CaseDefault = AExpr++type ConstBit = Bit++type ColId = Ident++type ColLabel = Ident++type Name = ColId++type CursorName = Name++type AttrName = ColLabel++type TypeModifiers = ExprList++type Collate = AnyName++type Class = AnyName++type TypeFunctionName = Ident
+ library-internal/PostgresqlSyntax/Ast/AExpr.hs view
@@ -0,0 +1,462 @@+module PostgresqlSyntax.Ast.AExpr+  ( AExpr (..),+    filteredParser,+    isBoundedAExprOperand,+    safeAExprOperand,+    selectWithParensAExpr,+    refineToSelectWithParens,+    canonicalize,+  )+where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AExprReversableOp+import PostgresqlSyntax.Ast.AnyName hiding (filteredParser)+import PostgresqlSyntax.Ast.CExpr (CExpr)+import qualified PostgresqlSyntax.Ast.CExpr as CExpr+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.QualOp+import PostgresqlSyntax.Ast.Row+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import PostgresqlSyntax.Ast.SubType+import PostgresqlSyntax.Ast.SubqueryOp+import PostgresqlSyntax.Ast.SymbolicExprBinOp+import PostgresqlSyntax.Ast.Typename+import PostgresqlSyntax.Ast.VerbalExprBinOp+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- a_expr:+--   | c_expr+--   | a_expr TYPECAST Typename+--   | a_expr COLLATE any_name+--   | a_expr AT TIME ZONE a_expr+--   | '+' a_expr+--   | '-' a_expr+--   | a_expr '+' a_expr+--   | a_expr '-' a_expr+--   | a_expr '*' a_expr+--   | a_expr '/' a_expr+--   | a_expr '%' a_expr+--   | a_expr '^' a_expr+--   | a_expr '<' a_expr+--   | a_expr '>' a_expr+--   | a_expr '=' a_expr+--   | a_expr LESS_EQUALS a_expr+--   | a_expr GREATER_EQUALS a_expr+--   | a_expr NOT_EQUALS a_expr+--   | a_expr qual_Op a_expr+--   | qual_Op a_expr+--   | a_expr AND a_expr+--   | a_expr OR a_expr+--   | NOT a_expr+--   | NOT_LA a_expr+--   | a_expr LIKE a_expr+--   | a_expr LIKE a_expr ESCAPE a_expr+--   | a_expr NOT_LA LIKE a_expr+--   | a_expr NOT_LA LIKE a_expr ESCAPE a_expr+--   | a_expr ILIKE a_expr+--   | a_expr ILIKE a_expr ESCAPE a_expr+--   | a_expr NOT_LA ILIKE a_expr+--   | a_expr NOT_LA ILIKE a_expr ESCAPE a_expr+--   | a_expr SIMILAR TO a_expr+--   | a_expr SIMILAR TO a_expr ESCAPE a_expr+--   | a_expr NOT_LA SIMILAR TO a_expr+--   | a_expr NOT_LA SIMILAR TO a_expr ESCAPE a_expr+--   | a_expr IS NULL_P+--   | a_expr ISNULL+--   | a_expr IS NOT NULL_P+--   | a_expr NOTNULL+--   | row OVERLAPS row+--   | a_expr IS TRUE_P+--   | a_expr IS NOT TRUE_P+--   | a_expr IS FALSE_P+--   | a_expr IS NOT FALSE_P+--   | a_expr IS UNKNOWN+--   | a_expr IS NOT UNKNOWN+--   | a_expr IS DISTINCT FROM a_expr+--   | a_expr IS NOT DISTINCT FROM a_expr+--   | a_expr IS OF '(' type_list ')'+--   | a_expr IS NOT OF '(' type_list ')'+--   | a_expr BETWEEN opt_asymmetric b_expr AND a_expr+--   | a_expr NOT_LA BETWEEN opt_asymmetric b_expr AND a_expr+--   | a_expr BETWEEN SYMMETRIC b_expr AND a_expr+--   | a_expr NOT_LA BETWEEN SYMMETRIC b_expr AND a_expr+--   | a_expr IN_P in_expr+--   | a_expr NOT_LA IN_P in_expr+--   | a_expr subquery_Op sub_type select_with_parens+--   | a_expr subquery_Op sub_type '(' a_expr ')'+--   | UNIQUE select_with_parens+--   | a_expr IS DOCUMENT_P+--   | a_expr IS NOT DOCUMENT_P+--   | DEFAULT+-- @+data AExpr+  = CExprAExpr CExpr+  | TypecastAExpr AExpr Typename+  | CollateAExpr AExpr AnyName+  | AtTimeZoneAExpr AExpr AExpr+  | PlusAExpr AExpr+  | MinusAExpr AExpr+  | SymbolicBinOpAExpr AExpr SymbolicExprBinOp AExpr+  | PrefixQualOpAExpr QualOp AExpr+  | AndAExpr AExpr AExpr+  | OrAExpr AExpr AExpr+  | NotAExpr AExpr+  | VerbalExprBinOpAExpr AExpr Bool VerbalExprBinOp AExpr (Maybe AExpr)+  | ReversableOpAExpr AExpr Bool AExprReversableOp+  | IsnullAExpr AExpr+  | NotnullAExpr AExpr+  | OverlapsAExpr Row Row+  | SubqueryAExpr AExpr SubqueryOp SubType (Either SelectWithParens AExpr)+  | UniqueAExpr SelectWithParens+  | DefaultAExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AExpr where+  toTextBuilder settings = \case+    CExprAExpr a -> toTextBuilder settings a+    TypecastAExpr a b -> renderOperand a <> " :: " <> toTextBuilder settings b+    CollateAExpr a b -> renderOperand a <> " COLLATE " <> toTextBuilder settings b+    AtTimeZoneAExpr a b -> renderOperand a <> " AT TIME ZONE " <> toTextBuilder settings b+    PlusAExpr a -> "+ " <> toTextBuilder settings a+    MinusAExpr a -> "- " <> toTextBuilder settings a+    SymbolicBinOpAExpr a b c -> renderOperand a <> " " <> toTextBuilder settings b <> " " <> toTextBuilder settings c+    PrefixQualOpAExpr a b -> toTextBuilder settings a <> " " <> toTextBuilder settings b+    AndAExpr a b -> renderOperand a <> " AND " <> toTextBuilder settings b+    OrAExpr a b -> renderOperand a <> " OR " <> toTextBuilder settings b+    NotAExpr a -> "NOT " <> toTextBuilder settings a+    VerbalExprBinOpAExpr a b c d e -> renderOperand a <> " " <> bool "" "NOT " b <> toTextBuilder settings c <> " " <> renderVerbalRhs e d <> foldMap (mappend " ESCAPE " . toTextBuilder settings) e+    ReversableOpAExpr a b c -> renderOperand a <> " " <> renderAExprReversableOp b c+    IsnullAExpr a -> renderOperand a <> " ISNULL"+    NotnullAExpr a -> renderOperand a <> " NOTNULL"+    OverlapsAExpr a b -> toTextBuilder settings a <> " OVERLAPS " <> toTextBuilder settings b+    SubqueryAExpr a b c d -> renderOperand a <> " " <> toTextBuilder settings b <> " " <> toTextBuilder settings c <> " " <> either (toTextBuilder settings) (TextBuilders.renderInParens . toTextBuilder settings) d+    UniqueAExpr a -> "UNIQUE " <> toTextBuilder settings a+    DefaultAExpr -> "DEFAULT"+    where+      -- Renders an operand sitting in the left\/accumulator position of a+      -- suffix production (the @a@ that 'customizedParser'\'s @suffixRec@+      -- threads through). Every alternative in @suffix@ parses its+      -- right-hand operand via an unrestricted recursive @a_expr@ call, so+      -- rendering it plainly always reconstructs the same shape on reparse.+      -- The *left* position is different: control only returns to+      -- @suffixRec@'s loop after a __bounded__ production — one that+      -- doesn't itself end in an unrestricted recursive @a_expr@. A value+      -- shaped like 'PlusAExpr'\/'MinusAExpr'\/'NotAExpr'\/+      -- 'PrefixQualOpAExpr'\/'AtTimeZoneAExpr'\/'SymbolicBinOpAExpr'\/+      -- 'AndAExpr'\/'OrAExpr'\/'VerbalExprBinOpAExpr', or a 'ReversableOpAExpr'+      -- whose 'PostgresqlSyntax.Ast.AExprReversableOp' ends in one too, is+      -- unbounded — placed there bare, it would greedily re-absorb whatever+      -- follows on reparse (e.g. rendering @SymbolicBinOpAExpr (NotAExpr x)+      -- op y@ plainly as @NOT x op y@ reparses as @NotAExpr (SymbolicBinOpAExpr+      -- x op y)@). Parenthesizing it, via the existing @'(' a_expr ')'@+      -- 'PostgresqlSyntax.Ast.CExpr' production, keeps rendering correct for+      -- any 'AExpr' value, whether or not the parser itself could have+      -- produced it in that position.+      renderOperand a+        | isBoundedAExprOperand a = toTextBuilder settings a+        | otherwise = TextBuilders.renderInParens (toTextBuilder settings a)+      -- The @d@ operand of a @LIKE@\/@ILIKE@\/@SIMILAR TO@ production, when+      -- it has a trailing @ESCAPE@ clause of its own (@e@). Since @d@ is+      -- parsed via an unrestricted recursive @a_expr@, rendering it bare+      -- when it's unbounded (see 'isBoundedAExprOperand') — e.g. a dangling+      -- operator, or an escape-less 'VerbalExprBinOpAExpr' whose own greedy+      -- @optional escape@ check would otherwise swallow the text meant for+      -- \*this* production's @ESCAPE@ — reparses differently. Bounded shapes+      -- (a column reference, a constant, an already-parenthesized+      -- expression, DEFAULT, …) always terminate cleanly and never need the+      -- extra parens, exactly like @renderOperand@'s left position.+      renderVerbalRhs e d = case e of+        Nothing -> toTextBuilder settings d+        Just _+          | isBoundedAExprOperand d -> toTextBuilder settings d+          | otherwise -> TextBuilders.renderInParens (toTextBuilder settings d)+      -- Distinct from 'PostgresqlSyntax.Ast.AExprReversableOp'\'s own+      -- @toTextBuilder@ (which bakes in the "positive" @IS@\/@BETWEEN@\/@IN@+      -- Parsers.keyword but not the negation) — this one threads the external+      -- @Bool@ (@NOT@) in, mirroring the pre-extraction top-level+      -- @aExprReversableOp@ renderer.+      renderAExprReversableOp a = \case+        NullAExprReversableOp -> bool "IS " "IS NOT " a <> "NULL"+        TrueAExprReversableOp -> bool "IS " "IS NOT " a <> "TRUE"+        FalseAExprReversableOp -> bool "IS " "IS NOT " a <> "FALSE"+        UnknownAExprReversableOp -> bool "IS " "IS NOT " a <> "UNKNOWN"+        DistinctFromAExprReversableOp b -> bool "IS " "IS NOT " a <> "DISTINCT FROM " <> toTextBuilder settings b+        OfAExprReversableOp b -> bool "IS " "IS NOT " a <> "OF " <> TextBuilders.renderInParens (toTextBuilder settings b)+        BetweenAExprReversableOp b c d -> bool "" "NOT " a <> bool "BETWEEN " "BETWEEN ASYMMETRIC " b <> toTextBuilder settings c <> " AND " <> toTextBuilder settings d+        BetweenSymmetricAExprReversableOp b c -> bool "" "NOT " a <> "BETWEEN SYMMETRIC " <> toTextBuilder settings b <> " AND " <> toTextBuilder settings c+        InAExprReversableOp b -> bool "" "NOT " a <> "IN " <> toTextBuilder settings b+        DocumentAExprReversableOp -> bool "IS " "IS NOT " a <> "DOCUMENT"+  parser settings = customizedParser settings (parser settings)++-- |+-- Parameterized over the 'PostgresqlSyntax.Ast.CExpr' parser embedded at the+-- base case — the only axis 'filteredParser' needs to customize (via+-- 'PostgresqlSyntax.Ast.CExpr.customizedParser'). Every other occurrence of+-- @a_expr@\/@b_expr@\/@select_with_parens@ in the grammar below uses the+-- ordinary, unfiltered parsers, exactly as the pre-extraction+-- @customizedAExpr@ did (its @bExpr@\/@selectWithParens@ references were+-- never threaded through the @cExpr@ parameter either).+customizedParser :: Settings -> Parser CExpr -> Parser AExpr+customizedParser settings cExpr = suffixRec base suffix+  where+    aExpr = customizedParser settings cExpr+    base =+      asum+        [ DefaultAExpr <$ Parsers.keyword "default",+          UniqueAExpr <$> (Parsers.keyword "unique" *> Parsers.space1 *> parser settings),+          Parsers.qualOpExpr settings aExpr PrefixQualOpAExpr,+          PlusAExpr <$> Parsers.plusedExpr aExpr,+          MinusAExpr <$> Parsers.minusedExpr aExpr,+          NotAExpr <$> (Parsers.keyword "not" *> Parsers.space1 *> aExpr),+          CExprAExpr <$> cExpr+        ]+    suffix a =+      asum+        [ overlapsSuffix settings a,+          do+            Parsers.space1+            b <- Parser.wrapToHead (parser settings)+            Parsers.space1+            c <- Parser.wrapToHead (parser settings)+            Parsers.space+            d <- Left <$> Parser.wrapToHead (parser settings) <|> Right <$> Parsers.inParens aExpr+            return (SubqueryAExpr a b c d),+          Parsers.typecastExpr settings a TypecastAExpr,+          CollateAExpr a <$> (Parsers.space1 *> Parsers.keyword "collate" *> Parsers.space1 *> Parser.endHead *> parser settings),+          AtTimeZoneAExpr a <$> (Parsers.space1 *> Parsers.keyphrase "at time zone" *> Parsers.space1 *> Parser.endHead *> aExpr),+          Parsers.symbolicBinOpExpr settings a aExpr SymbolicBinOpAExpr,+          AndAExpr a <$> (Parsers.space1 *> Parsers.keyword "and" *> Parsers.space1 *> Parser.endHead *> aExpr),+          OrAExpr a <$> (Parsers.space1 *> Parsers.keyword "or" *> Parsers.space1 *> Parser.endHead *> aExpr),+          do+            Parsers.space1+            b <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+            c <- parser settings+            Parsers.space1+            Parser.endHead+            d <- aExpr+            e <- optional (Parsers.space1 *> Parsers.keyword "escape" *> Parsers.space1 *> Parser.endHead *> aExpr)+            return (VerbalExprBinOpAExpr a b c d e),+          do+            Parsers.space1+            Parsers.keyword "is"+            Parsers.space1+            Parser.endHead+            b <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+            c <-+              asum+                [ NullAExprReversableOp <$ Parsers.keyword "null",+                  TrueAExprReversableOp <$ Parsers.keyword "true",+                  FalseAExprReversableOp <$ Parsers.keyword "false",+                  UnknownAExprReversableOp <$ Parsers.keyword "unknown",+                  DistinctFromAExprReversableOp <$> (Parsers.keyword "distinct" *> Parsers.space1 *> Parsers.keyword "from" *> Parsers.space1 *> Parser.endHead *> aExpr),+                  OfAExprReversableOp <$> (Parsers.keyword "of" *> Parsers.space1 *> Parser.endHead *> Parsers.inParens (parser settings)),+                  DocumentAExprReversableOp <$ Parsers.keyword "document"+                ]+            return (ReversableOpAExpr a b c),+          do+            Parsers.space1+            b <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+            Parsers.keyword "between"+            Parsers.space1+            Parser.endHead+            c <-+              asum+                [ BetweenSymmetricAExprReversableOp <$ (Parsers.keyword "symmetric" *> Parsers.space1),+                  BetweenAExprReversableOp True <$ (Parsers.keyword "asymmetric" *> Parsers.space1),+                  pure (BetweenAExprReversableOp False)+                ]+            d <- parser settings+            Parsers.space1+            Parsers.keyword "and"+            Parsers.space1+            e <- aExpr+            return (ReversableOpAExpr a b (c d e)),+          do+            Parsers.space1+            b <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+            Parsers.keyword "in"+            Parsers.space+            c <- InAExprReversableOp <$> parser settings+            return (ReversableOpAExpr a b c),+          IsnullAExpr a <$ (Parsers.space1 *> Parsers.keyword "isnull"),+          NotnullAExpr a <$ (Parsers.space1 *> Parsers.keyword "notnull")+        ]++-- |+-- The @OVERLAPS@ operator, as a suffix of an already parsed left operand.+-- Reinterprets the already-parsed base 'AExpr' as a 'Row' rather than+-- speculatively parsing a @row@ on top of it — see the original+-- @overlapsSuffix@ in the pre-extraction @PostgresqlSyntax.Parsing@ for the+-- exponential-blowup rationale this avoids.+overlapsSuffix :: Settings -> AExpr -> Parser AExpr+overlapsSuffix settings a = do+  b <- maybe empty pure (aExprRow a)+  Parsers.space1+  Parsers.keyword "overlaps"+  Parser.endHead+  Parsers.space1+  c <- parser settings+  return (OverlapsAExpr b c)+  where+    aExprRow = \case+      CExprAExpr (CExpr.ExplicitRowCExpr x) -> Just (ExplicitRowRow x)+      CExprAExpr (CExpr.ImplicitRowCExpr x) -> Just (ImplicitRowRow x)+      _ -> Nothing++-- | 'parser', but rejecting the given words when they'd otherwise be+-- accepted as a trailing bare column-reference identifier. Needed by+-- "PostgresqlSyntax.Ast.SortBy", which must not let @a_expr@ swallow a+-- Parsers.keyword (@USING@\/@ASC@\/@DESC@\/@NULLS@) that is meant to terminate it.+filteredParser :: Settings -> [Text] -> Parser AExpr+filteredParser settings excluded = customizedParser settings (CExpr.customizedParser settings (Parsers.filteredColIdLike UnquotedIdent (parser settings) excluded))++-- |+-- Whether the given 'AExpr' is safe to place in the left\/accumulator+-- position of a suffix production without parenthesizing it — see+-- @renderOperand@ in the 'IsAst' instance above for why that position is+-- special. A shape is bounded when parsing it can never end in an+-- unrestricted recursive @a_expr@ call, i.e. control is guaranteed to+-- return to @suffixRec@'s loop once it's done.+--+-- Note this predicate is purely about operator precedence and+-- associativity: an unbounded shape is one whose own rendering ends in an+-- unrestricted recursive @a_expr@, so placed bare in the left position it+-- would re-absorb the suffix that follows (e.g. rendering+-- @SymbolicBinOpAExpr (NotAExpr x) op y@ plainly as @NOT x op y@ reparses+-- as @NotAExpr (SymbolicBinOpAExpr x op y)@). It is /not/ a general+-- terminator-keyword guard — it isn't a general-purpose mechanism against+-- an expression swallowing a keyword that terminates an enclosing+-- production; the only shape that ever created that hazard by construction+-- was the postfix @a_expr qual_Op@ production, which no longer exists here+-- or in @references/gram.y@ (see gram.y:15985,15987; Postgres removed+-- postfix operators in v14). It does incidentally get reused for that+-- purpose in "PostgresqlSyntax.Ast.TargetEl" (to stop an @OrAExpr@'s right+-- operand from absorbing a following implicit alias) — that's just one+-- call site's use of it, not evidence of general applicability.+isBoundedAExprOperand :: AExpr -> Bool+isBoundedAExprOperand = \case+  PlusAExpr {} -> False+  MinusAExpr {} -> False+  NotAExpr {} -> False+  PrefixQualOpAExpr {} -> False+  AtTimeZoneAExpr {} -> False+  SymbolicBinOpAExpr {} -> False+  AndAExpr {} -> False+  OrAExpr {} -> False+  VerbalExprBinOpAExpr {} -> False+  ReversableOpAExpr _ _ c -> case c of+    DistinctFromAExprReversableOp {} -> False+    BetweenAExprReversableOp {} -> False+    BetweenSymmetricAExprReversableOp {} -> False+    _ -> True+  _ -> True++-- |+-- A generator for the left\/accumulator position of a suffix production+-- (see 'isBoundedAExprOperand'): whatever the given generator produces gets+-- wrapped in an explicit @'(' a_expr ')'@ (via 'CExpr.InParensCExpr') when+-- it wouldn't otherwise be reachable there, so the result always round-trips+-- through 'parser'.+safeAExprOperand :: Qc.Gen AExpr -> Qc.Gen AExpr+safeAExprOperand gen = do+  a <- gen+  pure $+    if isBoundedAExprOperand a+      then a+      else CExprAExpr (CExpr.InParensCExpr a Nothing)++-- |+-- Smart constructor wrapping a bare 'SelectWithParens' as an 'AExpr', for+-- modules that can only see 'AExpr' via its @hs-boot@ (which keeps it+-- abstract to break an import cycle) — see "PostgresqlSyntax.Ast.InExpr",+-- which needs it to canonicalize a @select_with_parens@\/@expr_list@+-- ambiguity.+selectWithParensAExpr :: SelectWithParens -> AExpr+selectWithParensAExpr a = CExprAExpr (CExpr.SelectWithParensCExpr a Nothing)++-- |+-- If an 'AExpr' is a bare, indirection-less 'PostgresqlSyntax.Ast.CExpr.SelectWithParensCExpr'+-- wrapping, returns the wrapped 'SelectWithParens'. The inverse of+-- 'selectWithParensAExpr', exposed for the same @hs-boot@-abstraction reason+-- — see "PostgresqlSyntax.Ast.CExpr", which needs it to canonicalize an+-- @'(' a_expr ')'@\/@select_with_parens@ ambiguity analogous to the one+-- described there.+refineToSelectWithParens :: AExpr -> Maybe SelectWithParens+refineToSelectWithParens = \case+  CExprAExpr (CExpr.SelectWithParensCExpr a Nothing) -> Just a+  _ -> Nothing++-- |+-- Collapses the non-canonical @Right@-wrapping-a-bare-@select_with_parens@+-- shape of 'SubqueryAExpr'\'s final field to the @Left@ shape the parser+-- actually produces for it.+--+-- @a_expr subquery_Op sub_type select_with_parens@ (i.e. @Left@) and+-- @a_expr subquery_Op sub_type '(' a_expr ')'@ (i.e. @Right@) overlap+-- whenever the parenthesized @a_expr@ is itself nothing but a bare,+-- indirection-less @select_with_parens@: both parse @x = ANY ((select 1))@.+-- @suffix@ tries the @select_with_parens@ alternative before the+-- parenthesized @a_expr@ one (see the @d <- Left <$> ... <|> Right <$> ...@+-- line above), so that's always what the parser returns — never @Right@ —+-- making the latter non-canonical for this shape. Both 'arbitrary' and+-- 'shrink' can otherwise construct it, which renders fine but parses back to+-- a different, canonical value and so breaks the roundtrip property.+canonicalize :: AExpr -> AExpr+canonicalize = \case+  SubqueryAExpr a b c (Right d)+    | Just inner <- refineToSelectWithParens d -> SubqueryAExpr a b c (Left inner)+  other -> other++instance Qc.Arbitrary AExpr where+  shrink = fmap canonicalize . Qc.genericShrink+  arbitrary =+    fmap canonicalize $ Qc.sized $ \n ->+      if n <= 1+        then pure DefaultAExpr+        else+          Qc.oneof+            [ CExprAExpr <$> Qc.arbitrary,+              pure DefaultAExpr,+              TypecastAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary,+              CollateAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary,+              AtTimeZoneAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Gens.downscale Qc.arbitrary,+              PlusAExpr <$> Gens.downscale Qc.arbitrary,+              MinusAExpr <$> Gens.downscale Qc.arbitrary,+              SymbolicBinOpAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              PrefixQualOpAExpr <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              AndAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Gens.downscale Qc.arbitrary,+              OrAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Gens.downscale Qc.arbitrary,+              NotAExpr <$> Gens.downscale Qc.arbitrary,+              ( do+                  a <- safeAExprOperand (Gens.downscale Qc.arbitrary)+                  b <- Qc.arbitrary+                  c <- Qc.arbitrary+                  e <- Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)+                  -- See @renderVerbalRhs@ in the 'IsAst' instance above:+                  -- whenever there's an escape clause, an unbounded @d@ must+                  -- be pre-wrapped in parens so the generated value already+                  -- matches what parsing the (necessarily parenthesized)+                  -- rendering reconstructs — the same rule 'safeAExprOperand'+                  -- applies for the left/accumulator position.+                  d <- case e of+                    Nothing -> Gens.downscale Qc.arbitrary+                    Just _ -> safeAExprOperand (Gens.downscale Qc.arbitrary)+                  pure (VerbalExprBinOpAExpr a b c d e)+              ),+              ReversableOpAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary <*> Qc.arbitrary,+              IsnullAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary),+              NotnullAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary),+              OverlapsAExpr <$> Qc.arbitrary <*> Qc.arbitrary,+              SubqueryAExpr <$> safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary <*> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              UniqueAExpr <$> Gens.downscale Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/AExpr.hs-boot view
@@ -0,0 +1,39 @@+module PostgresqlSyntax.Ast.AExpr where++import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Bool, Data, Eq, Maybe, Ord, Parser, Show, Text)+import PostgresqlSyntax.Settings (Settings)+import Test.QuickCheck (Arbitrary, Gen)++data AExpr++instance Show AExpr++instance Eq AExpr++instance Ord AExpr++instance Data AExpr++instance IsAst AExpr++instance Arbitrary AExpr++-- | 'parser', but rejecting the given words when they'd otherwise be+-- accepted as a trailing bare column-reference identifier. Needed by+-- "PostgresqlSyntax.Ast.SortBy", which must not let @a_expr@ swallow a+-- keyword (@USING@\/@ASC@\/@DESC@\/@NULLS@) that is meant to terminate it.+filteredParser :: Settings -> [Text] -> Parser AExpr++-- | See "PostgresqlSyntax.Ast.AExpr" for the full documentation.+isBoundedAExprOperand :: AExpr -> Bool++-- | See "PostgresqlSyntax.Ast.AExpr" for the full documentation.+safeAExprOperand :: Gen AExpr -> Gen AExpr++-- | See "PostgresqlSyntax.Ast.AExpr" for the full documentation.+selectWithParensAExpr :: SelectWithParens -> AExpr++-- | See "PostgresqlSyntax.Ast.AExpr" for the full documentation.+refineToSelectWithParens :: AExpr -> Maybe SelectWithParens
+ library-internal/PostgresqlSyntax/Ast/AExprReversableOp.hs view
@@ -0,0 +1,113 @@+module PostgresqlSyntax.Ast.AExprReversableOp where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import {-# SOURCE #-} PostgresqlSyntax.Ast.BExpr (BExpr)+import PostgresqlSyntax.Ast.InExpr+import PostgresqlSyntax.Ast.TypeList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- The part of the following productions that follows @a_expr [NOT]@ /+-- @b_expr [NOT]@ — the leading @IS@\/@NOT@ toggle itself is external to this+-- type (it lives alongside it, e.g. in @ReversableOpAExpr AExpr Bool+-- AExprReversableOp@), mirroring how 'PostgresqlSyntax.Ast.VerbalExprBinOp'+-- keeps @NOT_LA@ external. Only the @IS@\/@BETWEEN@\/@IN@ Parsers.keyword that's+-- intrinsic to each specific alternative (as opposed to the shared negation)+-- is captured here.+--+-- ==== References+-- @+--   | a_expr IS NULL_P+--   | a_expr IS TRUE_P+--   | a_expr IS FALSE_P+--   | a_expr IS UNKNOWN+--   | a_expr IS DISTINCT FROM a_expr+--   | a_expr IS OF '(' type_list ')'+--   | a_expr BETWEEN opt_asymmetric b_expr AND a_expr+--   | a_expr BETWEEN SYMMETRIC b_expr AND a_expr+--   | a_expr IN_P in_expr+--   | a_expr IS DOCUMENT_P+-- @+data AExprReversableOp+  = NullAExprReversableOp+  | TrueAExprReversableOp+  | FalseAExprReversableOp+  | UnknownAExprReversableOp+  | DistinctFromAExprReversableOp AExpr+  | OfAExprReversableOp TypeList+  | BetweenAExprReversableOp Bool BExpr AExpr+  | BetweenSymmetricAExprReversableOp BExpr AExpr+  | InAExprReversableOp InExpr+  | DocumentAExprReversableOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AExprReversableOp where+  toTextBuilder settings = \case+    NullAExprReversableOp -> "IS NULL"+    TrueAExprReversableOp -> "IS TRUE"+    FalseAExprReversableOp -> "IS FALSE"+    UnknownAExprReversableOp -> "IS UNKNOWN"+    DistinctFromAExprReversableOp b -> "IS DISTINCT FROM " <> toTextBuilder settings b+    OfAExprReversableOp b -> "IS OF " <> TextBuilders.renderInParens (toTextBuilder settings b)+    BetweenAExprReversableOp b c d -> bool "BETWEEN " "BETWEEN ASYMMETRIC " b <> toTextBuilder settings c <> " AND " <> toTextBuilder settings d+    BetweenSymmetricAExprReversableOp b c -> "BETWEEN SYMMETRIC " <> toTextBuilder settings b <> " AND " <> toTextBuilder settings c+    InAExprReversableOp b -> "IN " <> toTextBuilder settings b+    DocumentAExprReversableOp -> "IS DOCUMENT"+  parser settings =+    asum+      [ Parsers.keyword "is"+          *> Parsers.space1+          *> Parser.endHead+          *> asum+            [ NullAExprReversableOp <$ Parsers.keyword "null",+              TrueAExprReversableOp <$ Parsers.keyword "true",+              FalseAExprReversableOp <$ Parsers.keyword "false",+              UnknownAExprReversableOp <$ Parsers.keyword "unknown",+              DistinctFromAExprReversableOp <$> (Parsers.keyword "distinct" *> Parsers.space1 *> Parsers.keyword "from" *> Parsers.space1 *> Parser.endHead *> parser settings),+              OfAExprReversableOp <$> (Parsers.keyword "of" *> Parsers.space1 *> Parser.endHead *> Parsers.inParens (parser settings)),+              DocumentAExprReversableOp <$ Parsers.keyword "document"+            ],+        do+          Parsers.keyword "between"+          Parsers.space1+          Parser.endHead+          c <-+            asum+              [ BetweenSymmetricAExprReversableOp <$ (Parsers.keyword "symmetric" *> Parsers.space1),+                BetweenAExprReversableOp True <$ (Parsers.keyword "asymmetric" *> Parsers.space1),+                pure (BetweenAExprReversableOp False)+              ]+          d <- parser settings+          Parsers.space1+          Parsers.keyword "and"+          Parsers.space1+          e <- parser settings+          return (c d e),+        InAExprReversableOp <$> (Parsers.keyword "in" *> Parsers.space *> parser settings)+      ]++instance Qc.Arbitrary AExprReversableOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then Qc.oneof [pure NullAExprReversableOp, pure TrueAExprReversableOp, pure FalseAExprReversableOp, pure UnknownAExprReversableOp, pure DocumentAExprReversableOp]+        else+          Qc.oneof+            [ pure NullAExprReversableOp,+              pure TrueAExprReversableOp,+              pure FalseAExprReversableOp,+              pure UnknownAExprReversableOp,+              DistinctFromAExprReversableOp <$> Gens.downscale Qc.arbitrary,+              OfAExprReversableOp <$> Gens.downscale Qc.arbitrary,+              BetweenAExprReversableOp <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              BetweenSymmetricAExprReversableOp <$> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              InAExprReversableOp <$> Gens.downscale Qc.arbitrary,+              pure DocumentAExprReversableOp+            ]
+ library-internal/PostgresqlSyntax/Ast/AexprConst.hs view
@@ -0,0 +1,126 @@+module PostgresqlSyntax.Ast.AexprConst where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Bconst+import PostgresqlSyntax.Ast.ConstTypename+import PostgresqlSyntax.Ast.Fconst+import PostgresqlSyntax.Ast.FuncConstArgs+import PostgresqlSyntax.Ast.FuncName+import PostgresqlSyntax.Ast.Iconst+import PostgresqlSyntax.Ast.Interval+import PostgresqlSyntax.Ast.Sconst+import PostgresqlSyntax.Ast.Xconst+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc+import qualified Text.Megaparsec as Megaparsec+import qualified Text.Megaparsec.Char as MegaparsecChar++-- |+-- ==== References+-- @+-- AexprConst:+--   |  Iconst+--   |  FCONST+--   |  Sconst+--   |  BCONST+--   |  XCONST+--   |  func_name Sconst+--   |  func_name '(' func_arg_list opt_sort_clause ')' Sconst+--   |  ConstTypename Sconst+--   |  ConstInterval Sconst opt_interval+--   |  ConstInterval '(' Iconst ')' Sconst+--   |  TRUE_P+--   |  FALSE_P+--   |  NULL_P+-- @+data AexprConst+  = IAexprConst Iconst+  | FAexprConst Fconst+  | SAexprConst Sconst+  | BAexprConst Bconst+  | XAexprConst Xconst+  | FuncAexprConst FuncName (Maybe FuncConstArgs) Sconst+  | ConstTypenameAexprConst ConstTypename Sconst+  | StringIntervalAexprConst Sconst (Maybe Interval)+  | IntIntervalAexprConst Iconst Sconst+  | BoolAexprConst Bool+  | NullAexprConst+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AexprConst where+  toTextBuilder settings = \case+    IAexprConst a -> toTextBuilder settings a+    FAexprConst a -> toTextBuilder settings a+    SAexprConst a -> toTextBuilder settings a+    BAexprConst a -> toTextBuilder settings a+    XAexprConst a -> toTextBuilder settings a+    FuncAexprConst a b c -> toTextBuilder settings a <> foldMap (TextBuilders.renderInParens . toTextBuilder settings) b <> " " <> toTextBuilder settings c+    ConstTypenameAexprConst a b -> toTextBuilder settings a <> " " <> toTextBuilder settings b+    StringIntervalAexprConst a b -> "INTERVAL " <> toTextBuilder settings a <> TextBuilders.suffixMaybe (toTextBuilder settings) b+    IntIntervalAexprConst a b -> "INTERVAL " <> TextBuilders.renderInParens (toTextBuilder settings a) <> " " <> toTextBuilder settings b+    BoolAexprConst a -> if a then "TRUE" else "FALSE"+    NullAexprConst -> "NULL"+  parser settings =+    asum+      [ do+          Parsers.keyword "interval"+          Parsers.space1+          Parser.endHead+          a <-+            asum+              [ do+                  a <- parser settings+                  Parser.endHead+                  b <- optional (Parsers.space1 *> parser settings)+                  return (StringIntervalAexprConst a b),+                do+                  a <- Parsers.inParens (parser settings)+                  Parsers.space1+                  Parser.endHead+                  b <- parser settings+                  return (IntIntervalAexprConst a b)+              ]+          return a,+        do+          a <- parser settings+          Parsers.space1+          Parser.endHead+          b <- parser settings+          return (ConstTypenameAexprConst a b),+        BoolAexprConst True <$ Parsers.keyword "true",+        BoolAexprConst False <$ Parsers.keyword "false",+        NullAexprConst <$ Parsers.keyword "null" <* Parser.parse (Megaparsec.notFollowedBy MegaparsecChar.alphaNumChar),+        either IAexprConst FAexprConst <$> (Right <$> parser settings <|> Left <$> parser settings),+        SAexprConst <$> parser settings,+        BAexprConst <$> parser settings,+        XAexprConst <$> parser settings,+        Parser.wrapToHead $ do+          a <- parser settings+          Parsers.space+          b <- Parsers.inParens (parser settings)+          Parsers.space1+          d <- parser settings+          return (FuncAexprConst a (Just b) d),+        FuncAexprConst <$> (Parser.wrapToHead (parser settings) <* Parsers.space1) <*> pure Nothing <*> parser settings+      ]++instance Qc.Arbitrary AexprConst where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ IAexprConst <$> Qc.arbitrary,+        FAexprConst <$> Qc.arbitrary,+        SAexprConst <$> Qc.arbitrary,+        BAexprConst <$> Qc.arbitrary,+        XAexprConst <$> Qc.arbitrary,+        FuncAexprConst <$> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary <*> Qc.arbitrary,+        ConstTypenameAexprConst <$> Qc.arbitrary <*> Qc.arbitrary,+        StringIntervalAexprConst <$> Qc.arbitrary <*> Qc.arbitrary,+        IntIntervalAexprConst <$> Qc.arbitrary <*> Qc.arbitrary,+        BoolAexprConst <$> Qc.arbitrary,+        pure NullAexprConst+      ]
+ library-internal/PostgresqlSyntax/Ast/AliasClause.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Ast.AliasClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.NameList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- alias_clause:+--   |  AS ColId '(' name_list ')'+--   |  AS ColId+--   |  ColId '(' name_list ')'+--   |  ColId+-- @+--+-- 'PostgresqlSyntax.Ast.ColId' is a bare alias to 'Ident', but its /parser/+-- (kept in "PostgresqlSyntax.Parsing" since @ColId@ itself isn't extracted+-- in this batch) is more permissive than plain 'Ident'. Since this module+-- sits below "PostgresqlSyntax.Parsing" (no import cycle allowed), that+-- ColId-flavored element parser is duplicated here (mirroring @colId@'s+-- definition), same as 'PostgresqlSyntax.Ast.NameList'.+data AliasClause = AliasClause Bool Ident (Maybe NameList)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AliasClause where+  toTextBuilder settings (AliasClause a b c) =+    TextBuilders.optLexemes+      [ if a then Just "AS" else Nothing,+        Just (toTextBuilder settings b),+        fmap (TextBuilders.renderInParens . toTextBuilder settings) c+      ]+  parser settings = do+    (as, alias) <- (True,) <$> (Parsers.keyword "as" *> Parsers.space1 *> Parser.endHead *> colIdLikeName) <|> (False,) <$> colIdLikeName+    columnAliases <- optional (Parsers.space1 *> Parsers.inParens (parser settings))+    return (AliasClause as alias columnAliases)+    where+      colIdLikeName =+        Parser.label "identifier" $+          parser settings+            <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)++instance Qc.Arbitrary AliasClause where+  shrink = Qc.genericShrink+  arbitrary = AliasClause <$> arbitrary <*> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/AllOp.hs view
@@ -0,0 +1,37 @@+module PostgresqlSyntax.Ast.AllOp where++import PostgresqlSyntax.Ast.MathOp+import PostgresqlSyntax.Ast.Op+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- all_Op:+--   | Op+--   | MathOp+-- @+data AllOp+  = OpAllOp Op+  | MathAllOp MathOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AllOp where+  toTextBuilder settings = \case+    OpAllOp a -> toTextBuilder settings a+    MathAllOp a -> toTextBuilder settings a+  parser settings =+    asum+      [ OpAllOp <$> parser settings,+        MathAllOp <$> parser settings+      ]++instance Qc.Arbitrary AllOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ OpAllOp <$> Qc.arbitrary,+        MathAllOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/AnyName.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Ast.AnyName where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Attrs+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- any_name:+--   | ColId+--   | ColId attrs+-- @+--+-- 'PostgresqlSyntax.Ast.ColId' is a bare alias to 'Ident', but its /parser/+-- (kept in "PostgresqlSyntax.Parsing" since @ColId@ itself isn't extracted+-- in this batch) is more permissive than plain 'Ident'. Since this module+-- sits below "PostgresqlSyntax.Parsing" (no import cycle allowed), that+-- ColId-flavored element parser is duplicated here (mirroring @colId@'s+-- definition), same as 'PostgresqlSyntax.Ast.NameList'. (This is also+-- exactly what "PostgresqlSyntax.Parsing"'s @customizedAnyName@ does with+-- its @colId@ argument; that generic helper stays in "PostgresqlSyntax.Parsing"+-- since its other caller, @filteredAnyName@, passes a filtered variant.)+data AnyName = AnyName Ident (Maybe Attrs)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AnyName where+  toTextBuilder settings (AnyName a b) = toTextBuilder settings a <> foldMap (toTextBuilder settings) b+  parser settings = AnyName <$> (Parser.wrapToHead colIdLikeName <* Parser.endHead) <*> optional (Parsers.space *> parser settings)+    where+      colIdLikeName =+        Parser.label "identifier" $+          parser settings+            <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)++instance Qc.Arbitrary AnyName where+  shrink = Qc.genericShrink+  arbitrary = AnyName <$> arbitrary <*> arbitrary++-- | 'parser', but rejecting the given words when they'd otherwise be+-- accepted as the leading identifier — needed by+-- "PostgresqlSyntax.Ast.IndexElem"'s @opt_class@ position, mirroring the+-- pre-extraction @filteredAnyName@.+filteredParser :: Settings -> [Text] -> Parser AnyName+filteredParser settings excluded = AnyName <$> (Parser.wrapToHead (Parsers.filteredColIdLike UnquotedIdent (parser settings) excluded) <* Parser.endHead) <*> optional (Parsers.space *> parser settings)
+ library-internal/PostgresqlSyntax/Ast/AnyOperator.hs view
@@ -0,0 +1,56 @@+module PostgresqlSyntax.Ast.AnyOperator where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AllOp+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- any_operator:+--   | all_Op+--   | ColId '.' any_operator+-- @+--+-- 'PostgresqlSyntax.Ast.ColId' is a bare alias to 'Ident', but its /parser/+-- (kept in "PostgresqlSyntax.Parsing" since @ColId@ itself isn't extracted+-- in this batch) is more permissive than plain 'Ident'. Since this module+-- sits below "PostgresqlSyntax.Parsing" (no import cycle allowed), that+-- ColId-flavored element parser is duplicated here (mirroring @colId@'s+-- definition), same as 'PostgresqlSyntax.Ast.NameList'.+data AnyOperator+  = AllOpAnyOperator AllOp+  | QualifiedAnyOperator Ident AnyOperator+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst AnyOperator where+  toTextBuilder settings = \case+    AllOpAnyOperator a -> toTextBuilder settings a+    QualifiedAnyOperator a b -> toTextBuilder settings a <> "." <> toTextBuilder settings b+  parser settings =+    asum+      [ AllOpAnyOperator <$> parser settings,+        QualifiedAnyOperator <$> colIdLikeName <*> (Parsers.space *> Parsers.char '.' *> Parsers.space *> parser settings)+      ]+    where+      colIdLikeName =+        Parser.label "identifier" $+          parser settings+            <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)++instance Qc.Arbitrary AnyOperator where+  shrink = Qc.genericShrink+  arbitrary = Qc.sized $ \n ->+    if n <= 1+      then AllOpAnyOperator <$> Qc.arbitrary+      else+        Qc.oneof+          [ AllOpAnyOperator <$> Qc.arbitrary,+            QualifiedAnyOperator <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary+          ]
+ library-internal/PostgresqlSyntax/Ast/ArrayBounds.hs view
@@ -0,0 +1,28 @@+module PostgresqlSyntax.Ast.ArrayBounds where++import PostgresqlSyntax.Ast.Iconst+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_array_bounds:+--   | opt_array_bounds '[' Iconst ']'+--   | opt_array_bounds '[' ']'+--   | EMPTY+-- @+newtype ArrayBounds = ArrayBounds (NonEmpty (Maybe Iconst))+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ArrayBounds where+  toTextBuilder settings (ArrayBounds a) = TextBuilders.spaceNonEmpty (TextBuilders.renderInBrackets . foldMap (toTextBuilder settings)) a+  parser settings = ArrayBounds <$> Parsers.sep1 Parsers.space (Parsers.inBrackets (optional (parser settings)))++instance Qc.Arbitrary ArrayBounds where+  shrink = Qc.genericShrink+  arbitrary = ArrayBounds <$> Gens.nonEmptyUpTo 3 (Qc.oneof [pure Nothing, Just <$> Qc.arbitrary])
+ library-internal/PostgresqlSyntax/Ast/ArrayExpr.hs view
@@ -0,0 +1,50 @@+module PostgresqlSyntax.Ast.ArrayExpr where++import PostgresqlSyntax.Ast.ArrayExprList+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- array_expr:+--   | '[' expr_list ']'+--   | '[' array_expr_list ']'+--   | '[' ']'+-- @+data ArrayExpr+  = ExprListArrayExpr ExprList+  | ArrayExprListArrayExpr ArrayExprList+  | EmptyArrayExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ArrayExpr where+  toTextBuilder settings =+    TextBuilders.renderInBrackets . \case+      ExprListArrayExpr a -> toTextBuilder settings a+      ArrayExprListArrayExpr a -> toTextBuilder settings a+      EmptyArrayExpr -> mempty+  parser settings =+    Parsers.inBrackets $+      asum+        [ ArrayExprListArrayExpr <$> parser settings,+          ExprListArrayExpr <$> parser settings,+          pure EmptyArrayExpr+        ]++instance Qc.Arbitrary ArrayExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then pure EmptyArrayExpr+        else+          Qc.oneof+            [ ExprListArrayExpr <$> Qc.arbitrary,+              ArrayExprListArrayExpr <$> Qc.arbitrary,+              pure EmptyArrayExpr+            ]
+ library-internal/PostgresqlSyntax/Ast/ArrayExpr.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.ArrayExpr where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data ArrayExpr++instance Show ArrayExpr++instance Eq ArrayExpr++instance Ord ArrayExpr++instance Data ArrayExpr++instance IsAst ArrayExpr++instance Arbitrary ArrayExpr
+ library-internal/PostgresqlSyntax/Ast/ArrayExprList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.ArrayExprList where++import {-# SOURCE #-} PostgresqlSyntax.Ast.ArrayExpr (ArrayExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- array_expr_list:+--   | array_expr+--   | array_expr_list ',' array_expr+-- @+newtype ArrayExprList = ArrayExprList (NonEmpty ArrayExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ArrayExprList where+  toTextBuilder settings (ArrayExprList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = ArrayExprList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary ArrayExprList where+  shrink = Qc.genericShrink+  arbitrary = ArrayExprList <$> Gens.nonEmptyUpTo 100 (Gens.downscale Qc.arbitrary)
+ library-internal/PostgresqlSyntax/Ast/AscDesc.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.AscDesc where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_asc_desc:+--   | ASC+--   | DESC+--   | EMPTY+-- @+data AscDesc = AscAscDesc | DescAscDesc+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst AscDesc where+  toTextBuilder _settings = \case+    AscAscDesc -> "ASC"+    DescAscDesc -> "DESC"+  parser _settings = Parsers.keyword "asc" $> AscAscDesc <|> Parsers.keyword "desc" $> DescAscDesc++instance Qc.Arbitrary AscDesc where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/Attrs.hs view
@@ -0,0 +1,45 @@+module PostgresqlSyntax.Ast.Attrs where++import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty+import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- attrs:+--   | '.' attr_name+--   | attrs '.' attr_name+-- @+--+-- 'PostgresqlSyntax.Ast.AttrName' is a bare alias to+-- 'PostgresqlSyntax.Ast.ColLabel' which is a bare alias to 'Ident', but the+-- @ColLabel@ /parser/ (kept in "PostgresqlSyntax.Parsing" since @ColLabel@+-- itself isn't extracted in this batch) is more permissive than plain+-- 'Ident': it additionally accepts the full @keyword@ lexical class as an+-- identifier. Since this module sits below "PostgresqlSyntax.Parsing" (no+-- import cycle allowed), that ColLabel-flavored element parser is+-- duplicated here (mirroring @colLabel@'s definition) rather than reused,+-- to preserve exact parsing behavior. (See 'PostgresqlSyntax.Ast.NameList'+-- for the same pattern applied to @ColId@.)+newtype Attrs = Attrs (NonEmpty Ident)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Attrs where+  toTextBuilder settings (Attrs a) = foldMap (mappend "." . toTextBuilder settings) a+  parser settings = Attrs <$> NonEmpty.some (Parsers.char '.' *> Parser.endHead *> Parsers.space *> colLabelLikeName)+    where+      colLabelLikeName =+        Parser.label "column label" $+          Parsers.keywordNameFromSet UnquotedIdent KeywordSet.keyword+            <|> parser settings++instance Qc.Arbitrary Attrs where+  shrink = Qc.genericShrink+  arbitrary = Attrs <$> Gens.nonEmptyUpTo 9 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/BExpr.hs view
@@ -0,0 +1,161 @@+module PostgresqlSyntax.Ast.BExpr where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.BExprIsOp+import PostgresqlSyntax.Ast.CExpr (CExpr)+import PostgresqlSyntax.Ast.QualOp+import PostgresqlSyntax.Ast.SymbolicExprBinOp+import PostgresqlSyntax.Ast.Typename+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- b_expr:+--   | c_expr+--   | b_expr TYPECAST Typename+--   | '+' b_expr+--   | '-' b_expr+--   | b_expr '+' b_expr+--   | b_expr '-' b_expr+--   | b_expr '*' b_expr+--   | b_expr '/' b_expr+--   | b_expr '%' b_expr+--   | b_expr '^' b_expr+--   | b_expr '<' b_expr+--   | b_expr '>' b_expr+--   | b_expr '=' b_expr+--   | b_expr LESS_EQUALS b_expr+--   | b_expr GREATER_EQUALS b_expr+--   | b_expr NOT_EQUALS b_expr+--   | b_expr qual_Op b_expr+--   | qual_Op b_expr+--   | b_expr IS DISTINCT FROM b_expr+--   | b_expr IS NOT DISTINCT FROM b_expr+--   | b_expr IS OF '(' type_list ')'+--   | b_expr IS NOT OF '(' type_list ')'+--   | b_expr IS DOCUMENT_P+--   | b_expr IS NOT DOCUMENT_P+-- @+--+-- Unlike 'PostgresqlSyntax.Ast.AExpr', nothing customizes this parser's+-- @c_expr@\/identifier axis externally, so — despite also being a+-- recursion hub — it needs no @customizedParser@\/@filteredParser@ export.+data BExpr+  = CExprBExpr CExpr+  | TypecastBExpr BExpr Typename+  | PlusBExpr BExpr+  | MinusBExpr BExpr+  | SymbolicBinOpBExpr BExpr SymbolicExprBinOp BExpr+  | QualOpBExpr QualOp BExpr+  | IsOpBExpr BExpr Bool BExprIsOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst BExpr where+  toTextBuilder settings = \case+    CExprBExpr a -> toTextBuilder settings a+    TypecastBExpr a b -> renderOperand a <> " :: " <> toTextBuilder settings b+    PlusBExpr a -> "+ " <> toTextBuilder settings a+    MinusBExpr a -> "- " <> toTextBuilder settings a+    SymbolicBinOpBExpr a b c -> renderOperand a <> " " <> toTextBuilder settings b <> " " <> toTextBuilder settings c+    QualOpBExpr a b -> toTextBuilder settings a <> " " <> toTextBuilder settings b+    IsOpBExpr a b c -> renderOperand a <> " " <> renderBExprIsOp b c+    where+      -- See 'PostgresqlSyntax.Ast.AExpr'\'s @renderOperand@ for the+      -- rationale — same left\/accumulator-position hazard, mirrored here+      -- for 'BExpr'\'s own (smaller) suffix grammar. Unlike 'AExpr', there's+      -- no @'(' b_expr ')'@ production to fall back on, so parenthesizing+      -- reinterprets the operand as an @a_expr@ via+      -- 'PostgresqlSyntax.Ast.CExpr'\'s @'(' a_expr ')'@ instead — still+      -- valid, semantically-equivalent SQL, just not the same 'BExpr' shape+      -- on reparse (only relevant to hand-constructed values; the+      -- 'Qc.Arbitrary' instance below never generates an operand needing+      -- this fallback).+      renderOperand a+        | isBoundedBExprOperand a = toTextBuilder settings a+        | otherwise = TextBuilders.renderInParens (toTextBuilder settings a)+      renderBExprIsOp a =+        mappend (bool "IS " "IS NOT " a) . \case+          DistinctFromBExprIsOp b -> "DISTINCT FROM " <> toTextBuilder settings b+          OfBExprIsOp b -> "OF " <> TextBuilders.renderInParens (toTextBuilder settings b)+          DocumentBExprIsOp -> "DOCUMENT"+  parser settings = suffixRec base suffix+    where+      bExpr = suffixRec base suffix+      base =+        asum+          [ Parsers.qualOpExpr settings bExpr QualOpBExpr,+            PlusBExpr <$> Parsers.plusedExpr bExpr,+            MinusBExpr <$> Parsers.minusedExpr bExpr,+            CExprBExpr <$> parser settings+          ]+      suffix a =+        asum+          [ Parsers.typecastExpr settings a TypecastBExpr,+            Parsers.symbolicBinOpExpr settings a bExpr SymbolicBinOpBExpr,+            do+              Parsers.space1+              Parsers.keyword "is"+              Parsers.space1+              Parser.endHead+              b <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+              c <-+                asum+                  [ DistinctFromBExprIsOp <$> (Parsers.keyphrase "distinct from" *> Parsers.space1 *> Parser.endHead *> bExpr),+                    OfBExprIsOp <$> (Parsers.keyword "of" *> Parsers.space1 *> Parser.endHead *> Parsers.inParens (parser settings)),+                    DocumentBExprIsOp <$ Parsers.keyword "document"+                  ]+              return (IsOpBExpr a b c)+          ]++-- |+-- Whether the given 'BExpr' is safe to place in the left\/accumulator+-- position of a suffix production without parenthesizing it — see+-- 'IsAst' 'BExpr'\'s @renderOperand@. Mirrors+-- 'PostgresqlSyntax.Ast.AExpr.isBoundedAExprOperand'.+isBoundedBExprOperand :: BExpr -> Bool+isBoundedBExprOperand = \case+  PlusBExpr {} -> False+  MinusBExpr {} -> False+  QualOpBExpr {} -> False+  SymbolicBinOpBExpr {} -> False+  IsOpBExpr _ _ c -> case c of+    DistinctFromBExprIsOp {} -> False+    _ -> True+  _ -> True++-- |+-- A generator for the left\/accumulator position of a suffix production+-- (see 'isBoundedBExprOperand'). Unlike+-- 'PostgresqlSyntax.Ast.AExpr.safeAExprOperand', 'BExpr' has no+-- parenthesizing escape hatch of its own (see @renderOperand@ above), so an+-- unbounded draw is simply replaced by an always-bounded 'CExprBExpr'+-- instead of wrapped.+safeBExprOperand :: Qc.Gen BExpr -> Qc.Gen BExpr+safeBExprOperand gen = do+  a <- gen+  if isBoundedBExprOperand a+    then pure a+    else CExprBExpr <$> Qc.arbitrary++instance Qc.Arbitrary BExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then CExprBExpr <$> Qc.arbitrary+        else+          Qc.oneof+            [ CExprBExpr <$> Qc.arbitrary,+              TypecastBExpr <$> safeBExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary,+              PlusBExpr <$> Gens.downscale Qc.arbitrary,+              MinusBExpr <$> Gens.downscale Qc.arbitrary,+              SymbolicBinOpBExpr <$> safeBExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              QualOpBExpr <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              IsOpBExpr <$> safeBExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary <*> Gens.downscale Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/BExpr.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.BExpr where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data BExpr++instance Show BExpr++instance Eq BExpr++instance Ord BExpr++instance Data BExpr++instance IsAst BExpr++instance Arbitrary BExpr
+ library-internal/PostgresqlSyntax/Ast/BExprIsOp.hs view
@@ -0,0 +1,55 @@+module PostgresqlSyntax.Ast.BExprIsOp where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.BExpr (BExpr)+import PostgresqlSyntax.Ast.TypeList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- Renders\/parses only the \"positive\" form (@DISTINCT FROM ...@\/@OF+-- (...)@\/@DOCUMENT@), mirroring 'PostgresqlSyntax.Ast.AExprReversableOp':+-- the external @IS@\/@IS NOT@ toggle lives alongside this type in+-- 'PostgresqlSyntax.Ast.BExpr'\'s own @IsOpBExpr BExpr Bool BExprIsOp@+-- constructor and is rendered\/parsed there, not here.+--+-- ==== References+-- @+--   | b_expr IS DISTINCT FROM b_expr+--   | b_expr IS NOT DISTINCT FROM b_expr+--   | b_expr IS OF '(' type_list ')'+--   | b_expr IS NOT OF '(' type_list ')'+--   | b_expr IS DOCUMENT_P+--   | b_expr IS NOT DOCUMENT_P+-- @+data BExprIsOp+  = DistinctFromBExprIsOp BExpr+  | OfBExprIsOp TypeList+  | DocumentBExprIsOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst BExprIsOp where+  toTextBuilder settings = \case+    DistinctFromBExprIsOp b -> "DISTINCT FROM " <> toTextBuilder settings b+    OfBExprIsOp b -> "OF " <> TextBuilders.renderInParens (toTextBuilder settings b)+    DocumentBExprIsOp -> "DOCUMENT"+  parser settings =+    asum+      [ DistinctFromBExprIsOp <$> (Parsers.keyphrase "distinct from" *> Parsers.space1 *> Parser.endHead *> parser settings),+        OfBExprIsOp <$> (Parsers.keyword "of" *> Parsers.space1 *> Parser.endHead *> Parsers.inParens (parser settings)),+        DocumentBExprIsOp <$ Parsers.keyword "document"+      ]++instance Qc.Arbitrary BExprIsOp where+  shrink = Qc.genericShrink+  arbitrary =+    Gens.oneofRec+      [ pure DocumentBExprIsOp+      ]+      [ DistinctFromBExprIsOp <$> Qc.arbitrary,+        OfBExprIsOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/Bconst.hs view
@@ -0,0 +1,33 @@+module PostgresqlSyntax.Ast.Bconst where++import qualified Data.Text as Text+import qualified HeadedMegaparsec as Parser+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.Shrinks as Shrinks+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc+import qualified TextBuilder++-- |+-- ==== References+-- @+-- BCONST+-- @+newtype Bconst = Bconst Text+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Bconst where+  toTextBuilder _settings (Bconst a) = "B'" <> TextBuilder.text a <> "'"+  parser _settings = Parser.label "bit literal" $ do+    Parsers.string' "b'"+    Parser.endHead+    a <- Parsers.takeWhile1P (Just "0 or 1") (\b -> b == '0' || b == '1')+    Parsers.char '\''+    return (Bconst a)++instance Qc.Arbitrary Bconst where+  shrink (Bconst a) = Bconst <$> Shrinks.nonEmptyText a+  arbitrary = do+    len <- Qc.choose (1, 100)+    Bconst . Text.pack <$> Qc.vectorOf len (Qc.elements "01")
+ library-internal/PostgresqlSyntax/Ast/Bit.hs view
@@ -0,0 +1,43 @@+module PostgresqlSyntax.Ast.Bit where++import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.OptVarying+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- Bit:+--   | BitWithLength+--   | BitWithoutLength+-- ConstBit:+--   | BitWithLength+--   | BitWithoutLength+-- BitWithLength:+--   | BIT opt_varying '(' expr_list ')'+-- BitWithoutLength:+--   | BIT opt_varying+-- @+data Bit = Bit OptVarying (Maybe ExprList)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Bit where+  toTextBuilder settings (Bit a b) =+    TextBuilders.optLexemes+      [ Just "BIT",+        bool Nothing (Just "VARYING") (coerce a :: Bool),+        fmap (TextBuilders.renderInParens . toTextBuilder settings) b+      ]+  parser settings = do+    Parsers.keyword "bit"+    a <- parser settings+    b <- optional (Parsers.space1 *> Parsers.inParens (parser settings))+    return (Bit a b)++instance Qc.Arbitrary Bit where+  shrink = Qc.genericShrink+  arbitrary = Bit <$> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/CExpr.hs view
@@ -0,0 +1,190 @@+module PostgresqlSyntax.Ast.CExpr+  ( CExpr (..),+    customizedParser,+    canonicalize,+  )+where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr, refineToSelectWithParens)+import PostgresqlSyntax.Ast.AexprConst+import PostgresqlSyntax.Ast.ArrayExpr+import PostgresqlSyntax.Ast.CaseExpr+import PostgresqlSyntax.Ast.Columnref+import PostgresqlSyntax.Ast.ExplicitRow+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.FuncExpr+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.ImplicitRow+import PostgresqlSyntax.Ast.Indirection+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens, withParensSelectWithParens)+import qualified PostgresqlSyntax.Extras.NonEmpty as NonEmpty+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- c_expr:+--   | columnref+--   | AexprConst+--   | PARAM opt_indirection+--   | '(' a_expr ')' opt_indirection+--   | case_expr+--   | func_expr+--   | select_with_parens+--   | select_with_parens indirection+--   | EXISTS select_with_parens+--   | ARRAY select_with_parens+--   | ARRAY array_expr+--   | explicit_row+--   | implicit_row+--   | GROUPING '(' expr_list ')'+-- @+data CExpr+  = ColumnrefCExpr Columnref+  | AexprConstCExpr AexprConst+  | ParamCExpr Int (Maybe Indirection)+  | InParensCExpr AExpr (Maybe Indirection)+  | CaseCExpr CaseExpr+  | FuncCExpr FuncExpr+  | SelectWithParensCExpr SelectWithParens (Maybe Indirection)+  | ExistsCExpr SelectWithParens+  | ArrayCExpr (Either SelectWithParens ArrayExpr)+  | ExplicitRowCExpr ExplicitRow+  | ImplicitRowCExpr ImplicitRow+  | GroupingCExpr ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst CExpr where+  toTextBuilder settings = \case+    ColumnrefCExpr a -> toTextBuilder settings a+    AexprConstCExpr a -> toTextBuilder settings a+    ParamCExpr a b -> "$" <> TextBuilder.intDec a <> foldMap (toTextBuilder settings) b+    InParensCExpr a b -> TextBuilders.renderInParens (toTextBuilder settings a) <> foldMap (toTextBuilder settings) b+    CaseCExpr a -> toTextBuilder settings a+    FuncCExpr a -> toTextBuilder settings a+    SelectWithParensCExpr a b -> toTextBuilder settings a <> foldMap (toTextBuilder settings) b+    ExistsCExpr a -> "EXISTS " <> toTextBuilder settings a+    ArrayCExpr a -> "ARRAY " <> either (toTextBuilder settings) (toTextBuilder settings) a+    ExplicitRowCExpr a -> toTextBuilder settings a+    ImplicitRowCExpr a -> toTextBuilder settings a+    GroupingCExpr a -> "GROUPING " <> TextBuilders.renderInParens (toTextBuilder settings a)+  parser settings = customizedParser settings (colId settings)++-- |+-- Parameterized over the @ColId@-like identifier parser used by the plain+-- 'ColumnrefCExpr' alternative — the one place 'PostgresqlSyntax.Ast.AExpr'+-- \'s @filteredParser@ needs to customize. Every other alternative here+-- (parenthesized expressions, @ARRAY@, @EXISTS@, function calls, ...) always+-- uses the ordinary, unfiltered parsers for its nested @a_expr@\/+-- @select_with_parens@\/etc, exactly as the pre-extraction+-- @customizedCExpr@\/@parenthesizedExprCExpr@ did — the filtering doesn't+-- propagate past this one level.+customizedParser :: Settings -> Parser Ident -> Parser CExpr+customizedParser settings colIdParser =+  asum+    [ ParamCExpr <$> (Parsers.char '$' *> Parsers.decimal <* Parser.endHead) <*> optional (Parsers.space *> parser settings),+      CaseCExpr <$> parser settings,+      ExplicitRowCExpr <$> parser settings,+      Parsers.inParensWithClause (Parsers.keyword "grouping") (GroupingCExpr . ExprList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)),+      Parsers.keyword "exists" *> Parsers.space *> (ExistsCExpr <$> parser settings),+      do+        Parsers.keyword "array"+        Parsers.space+        asum+          [ ArrayCExpr . Right <$> parser settings,+            ArrayCExpr . Left <$> parser settings+          ],+      do+        a <- Parser.wrapToHead (parser settings)+        Parser.endHead+        b <- optional (Parsers.space *> parser settings)+        return (SelectWithParensCExpr a b),+      parenthesizedExprCExpr,+      AexprConstCExpr <$> Parser.wrapToHead (parser settings),+      FuncCExpr <$> parser settings,+      ColumnrefCExpr <$> customizedColumnref+    ]+  where+    customizedColumnref = do+      a <- Parser.wrapToHead colIdParser+      Parser.endHead+      b <- optional (Parsers.space *> parser settings)+      return (Columnref a b)++    -- See 'PostgresqlSyntax.Ast.AExpr'\'s doc on the sibling parser this+    -- replaces (@parenthesizedExprCExpr@\/implicit-row sharing trick) for+    -- why the single @a_expr@ parse is shared between the two endings.+    parenthesizedExprCExpr :: Parser CExpr+    parenthesizedExprCExpr = do+      Parsers.char '('+      Parsers.space+      a <- parser settings+      Parsers.space+      asum+        [ do+            Parsers.char ','+            Parser.endHead+            Parsers.space+            b <- Parsers.sep1 Parsers.commaSeparator (parser settings)+            Parsers.space+            Parsers.char ')'+            return $ ImplicitRowCExpr $ case NonEmpty.consAndUnsnoc a b of+              (c, d) -> ImplicitRow (ExprList c) d,+          do+            Parsers.char ')'+            Parser.endHead+            b <- optional (Parsers.space *> parser settings)+            return (InParensCExpr a b)+        ]++instance Qc.Arbitrary CExpr where+  shrink = fmap canonicalize . Qc.genericShrink+  arbitrary =+    fmap canonicalize $ Qc.sized $ \n ->+      if n <= 1+        then ColumnrefCExpr <$> Qc.arbitrary+        else+          Qc.oneof+            [ ColumnrefCExpr <$> Qc.arbitrary,+              AexprConstCExpr <$> Qc.arbitrary,+              ParamCExpr <$> Qc.choose (1, 19) <*> Qc.arbitrary,+              InParensCExpr <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+              CaseCExpr <$> Qc.arbitrary,+              FuncCExpr <$> Qc.arbitrary,+              SelectWithParensCExpr <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+              ExistsCExpr <$> Gens.downscale Qc.arbitrary,+              ArrayCExpr <$> Gens.downscale Qc.arbitrary,+              ExplicitRowCExpr <$> Qc.arbitrary,+              ImplicitRowCExpr <$> Qc.arbitrary,+              GroupingCExpr <$> Qc.arbitrary+            ]++-- |+-- Collapses the non-canonical @InParensCExpr@-wrapping-a-@SelectWithParensCExpr@+-- shape to the @SelectWithParensCExpr@\/@WithParensSelectWithParens@ shape the+-- parser actually produces for it.+--+-- @'(' a_expr ')' opt_indirection@ (i.e. 'InParensCExpr') and+-- @select_with_parens@ (i.e. 'SelectWithParensCExpr') overlap whenever the+-- inner @a_expr@ is itself nothing but a bare, indirection-less+-- @select_with_parens@: both parse @((select 1))@. 'customizedParser' tries+-- the @select_with_parens@ alternative before @parenthesizedExprCExpr@, so+-- that's always what the parser returns — never 'InParensCExpr' — making+-- the latter non-canonical for this shape. Both 'arbitrary' and 'shrink' can+-- otherwise construct it (shrinking the outer indirection to @Nothing@ is+-- exactly how it arises), which renders fine but parses back to a+-- different, canonical value and so breaks the roundtrip property.+canonicalize :: CExpr -> CExpr+canonicalize = \case+  InParensCExpr a outerIndirection+    | Just inner <- refineToSelectWithParens a ->+        SelectWithParensCExpr (withParensSelectWithParens inner) outerIndirection+  other -> other
+ library-internal/PostgresqlSyntax/Ast/CallStmt.hs view
@@ -0,0 +1,22 @@+module PostgresqlSyntax.Ast.CallStmt where++import PostgresqlSyntax.Ast.FuncApplication+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++newtype CallStmt+  = CallStmt FuncApplication+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst CallStmt where+  toTextBuilder settings (CallStmt a) = "CALL " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "call"+    Parsers.space1+    CallStmt <$> parser settings++instance Qc.Arbitrary CallStmt where+  shrink = Qc.genericShrink+  arbitrary = CallStmt <$> arbitrary
+ library-internal/PostgresqlSyntax/Ast/CaseExpr.hs view
@@ -0,0 +1,54 @@+module PostgresqlSyntax.Ast.CaseExpr where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.WhenClauseList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- case_expr:+--   | CASE case_arg when_clause_list case_default END_P+-- @+data CaseExpr = CaseExpr (Maybe AExpr) WhenClauseList (Maybe AExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst CaseExpr where+  toTextBuilder settings (CaseExpr a b c) =+    TextBuilders.optLexemes+      [ Just "CASE",+        fmap (toTextBuilder settings) a,+        Just (toTextBuilder settings b),+        fmap caseDefault c,+        Just "END"+      ]+    where+      caseDefault d = "ELSE " <> toTextBuilder settings d+  parser settings = Parser.label "case expression" $ do+    Parsers.keyword "case"+    Parsers.space1+    Parser.endHead+    arg <- optional (parser settings <* Parsers.space1)+    whenClauses <- parser settings+    Parsers.space1+    default' <- optional elseClause+    Parsers.keyword "end"+    pure (CaseExpr arg whenClauses default')+    where+      elseClause = do+        Parsers.keyword "else"+        Parsers.space1+        Parser.endHead+        a <- parser settings+        Parsers.space1+        return a++instance Qc.Arbitrary CaseExpr where+  shrink = Qc.genericShrink+  arbitrary = CaseExpr <$> Gens.terminatingMaybe (Gens.downscale arbitrary) <*> arbitrary <*> Gens.terminatingMaybe (Gens.downscale arbitrary)
+ library-internal/PostgresqlSyntax/Ast/Character.hs view
@@ -0,0 +1,57 @@+module PostgresqlSyntax.Ast.Character where++import PostgresqlSyntax.Ast.OptVarying+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- character:+--   | CHARACTER opt_varying+--   | CHAR_P opt_varying+--   | VARCHAR+--   | NATIONAL CHARACTER opt_varying+--   | NATIONAL CHAR_P opt_varying+--   | NCHAR opt_varying+-- @+data Character+  = CharacterCharacter OptVarying+  | CharCharacter OptVarying+  | VarcharCharacter+  | NationalCharacterCharacter OptVarying+  | NationalCharCharacter OptVarying+  | NcharCharacter OptVarying+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Character where+  toTextBuilder _settings = \case+    CharacterCharacter a -> "CHARACTER" <> bool "" " VARYING" (coerce a :: Bool)+    CharCharacter a -> "CHAR" <> bool "" " VARYING" (coerce a :: Bool)+    VarcharCharacter -> "VARCHAR"+    NationalCharacterCharacter a -> "NATIONAL CHARACTER" <> bool "" " VARYING" (coerce a :: Bool)+    NationalCharCharacter a -> "NATIONAL CHAR" <> bool "" " VARYING" (coerce a :: Bool)+    NcharCharacter a -> "NCHAR" <> bool "" " VARYING" (coerce a :: Bool)+  parser settings =+    asum+      [ CharacterCharacter <$> (Parsers.keyword "character" *> parser settings),+        CharCharacter <$> (Parsers.keyword "char" *> parser settings),+        VarcharCharacter <$ Parsers.keyword "varchar",+        NationalCharacterCharacter <$> (Parsers.keyphrase "national character" *> parser settings),+        NationalCharCharacter <$> (Parsers.keyphrase "national char" *> parser settings),+        NcharCharacter <$> (Parsers.keyword "nchar" *> parser settings)+      ]++instance Qc.Arbitrary Character where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ CharacterCharacter <$> Qc.arbitrary,+        CharCharacter <$> Qc.arbitrary,+        pure VarcharCharacter,+        NationalCharacterCharacter <$> Qc.arbitrary,+        NationalCharCharacter <$> Qc.arbitrary,+        NcharCharacter <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/Columnref.hs view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.Columnref where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident (Ident, colId)+import PostgresqlSyntax.Ast.Indirection+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- columnref:+--   | ColId+--   | ColId indirection+-- @+data Columnref = Columnref Ident (Maybe Indirection)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Columnref where+  toTextBuilder settings (Columnref a b) = toTextBuilder settings a <> foldMap (toTextBuilder settings) b+  parser settings = do+    a <- Parser.wrapToHead (colId settings)+    Parser.endHead+    b <- optional (Parsers.space *> parser settings)+    return (Columnref a b)++instance Qc.Arbitrary Columnref where+  shrink = Qc.genericShrink+  arbitrary = Columnref <$> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/CommonTableExpr.hs view
@@ -0,0 +1,59 @@+module PostgresqlSyntax.Ast.CommonTableExpr where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.PreparableStmt+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- common_table_expr:+--   |  name opt_name_list AS opt_materialized '(' PreparableStmt ')'+-- opt_materialized:+--   | MATERIALIZED+--   | NOT MATERIALIZED+--   | EMPTY+-- @+data CommonTableExpr = CommonTableExpr Ident (Maybe (NonEmpty Ident)) (Maybe Bool) PreparableStmt+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst CommonTableExpr where+  toTextBuilder settings (CommonTableExpr a b c d) =+    TextBuilders.optLexemes+      [ Just (toTextBuilder settings a),+        fmap (TextBuilders.renderInParens . TextBuilders.commaNonEmpty (toTextBuilder settings)) b,+        Just "AS",+        fmap materialization c,+        Just (TextBuilders.renderInParens (toTextBuilder settings d))+      ]+    where+      materialization = bool "NOT MATERIALIZED" "MATERIALIZED"+  parser settings = Parser.label "common table expression" $ do+    name <- colId settings <* Parsers.space <* Parser.endHead+    nameList <- optional (Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (colId settings)) <* Parsers.space1)+    Parsers.keyword "as"+    Parsers.space1+    materialized <- optional (materialized <* Parsers.space1)+    stmt <- Parsers.inParens (parser settings)+    return (CommonTableExpr name nameList materialized stmt)+    where+      materialized =+        True+          <$ Parsers.keyword "materialized"+            <|> False+          <$ Parsers.keyphrase "not materialized"++instance Qc.Arbitrary CommonTableExpr where+  shrink = Qc.genericShrink+  arbitrary =+    CommonTableExpr+      <$> Qc.arbitrary+      <*> Gens.terminatingMaybe (Gens.nonEmptyUpTo 6 Qc.arbitrary)+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/ConfExpr.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Ast.ConfExpr where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.IndexParams+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_conf_expr:+--   | '(' index_params ')' where_clause+--   | ON CONSTRAINT name+--   | EMPTY+-- @+--+-- @where_clause@ is inlined here as a bare 'PostgresqlSyntax.Ast.AExpr'+-- rather than going through 'PostgresqlSyntax.Ast.WhereClause'.+-- @name@ is a bare alias to 'PostgresqlSyntax.Ast.Ident'.+data ConfExpr+  = WhereConfExpr IndexParams (Maybe AExpr)+  | ConstraintConfExpr Ident+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ConfExpr where+  toTextBuilder settings = \case+    WhereConfExpr a b -> TextBuilders.renderInParens (toTextBuilder settings a) <> TextBuilders.suffixMaybe whereClause b+    ConstraintConfExpr a -> "ON CONSTRAINT " <> toTextBuilder settings a+    where+      whereClause a = "WHERE " <> toTextBuilder settings a+  parser settings =+    asum+      [ WhereConfExpr <$> Parsers.inParens (parser settings) <*> optional (Parsers.space *> whereClause),+        ConstraintConfExpr <$> (Parsers.keyword "on" *> Parsers.space1 *> Parsers.keyword "constraint" *> Parsers.space1 *> Parser.endHead *> colId settings)+      ]+    where+      whereClause = Parsers.keyword "where" *> Parsers.space1 *> Parser.endHead *> parser settings++instance Qc.Arbitrary ConfExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ WhereConfExpr <$> Qc.arbitrary <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary),+        ConstraintConfExpr <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/ConstCharacter.hs view
@@ -0,0 +1,41 @@+module PostgresqlSyntax.Ast.ConstCharacter where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Character+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- ConstCharacter:+--   | CharacterWithLength+--   | CharacterWithoutLength+-- CharacterWithLength:+--   | character '(' Iconst ')'+-- CharacterWithoutLength:+--   | character+-- @+data ConstCharacter = ConstCharacter Character (Maybe Int64)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ConstCharacter where+  toTextBuilder settings (ConstCharacter a b) = toTextBuilder settings a <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) b+  parser settings = ConstCharacter <$> (parser settings <* Parser.endHead) <*> optional (Parsers.space *> Parsers.inParens Parsers.decimal)++instance Qc.Arbitrary ConstCharacter where+  shrink = Qc.genericShrink++  -- The length here is parsed via 'Parsers.decimal' (unsigned), so it must+  -- never be negative — mirroring 'PostgresqlSyntax.Ast.IntervalSecond'\'s+  -- own @nonNegative@.+  arbitrary = ConstCharacter <$> arbitrary <*> Qc.oneof [pure Nothing, Just <$> nonNegativeInt64]+    where+      nonNegativeInt64 = Qc.sized (\n -> Qc.choose (0, cap n))+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/ConstDatetime.hs view
@@ -0,0 +1,69 @@+module PostgresqlSyntax.Ast.ConstDatetime where++import PostgresqlSyntax.Ast.Timezone+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- ConstDatetime:+--   | TIMESTAMP '(' Iconst ')' opt_timezone+--   | TIMESTAMP opt_timezone+--   | TIME '(' Iconst ')' opt_timezone+--   | TIME opt_timezone+-- @+data ConstDatetime+  = TimestampConstDatetime (Maybe Int64) (Maybe Timezone)+  | TimeConstDatetime (Maybe Int64) (Maybe Timezone)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ConstDatetime where+  toTextBuilder settings = \case+    TimestampConstDatetime a b ->+      TextBuilders.optLexemes+        [ Just "TIMESTAMP",+          fmap (TextBuilders.renderInParens . TextBuilder.int64Dec) a,+          fmap (toTextBuilder settings) b+        ]+    TimeConstDatetime a b ->+      TextBuilders.optLexemes+        [ Just "TIME",+          fmap (TextBuilders.renderInParens . TextBuilder.int64Dec) a,+          fmap (toTextBuilder settings) b+        ]+  parser settings =+    asum+      [ do+          Parsers.keyword "timestamp"+          a <- optional (Parsers.space1 *> Parsers.inParens Parsers.decimal)+          b <- optional (Parsers.space1 *> parser settings)+          return (TimestampConstDatetime a b),+        do+          Parsers.keyword "time"+          a <- optional (Parsers.space1 *> Parsers.inParens Parsers.decimal)+          b <- optional (Parsers.space1 *> parser settings)+          return (TimeConstDatetime a b)+      ]++instance Qc.Arbitrary ConstDatetime where+  shrink = Qc.genericShrink++  -- The precision here is parsed via 'Parsers.decimal' (unsigned), so it+  -- must never be negative — mirroring+  -- 'PostgresqlSyntax.Ast.IntervalSecond'\'s own @nonNegative@.+  arbitrary =+    Qc.oneof+      [ TimestampConstDatetime <$> nonNegativeMaybeInt64 <*> Qc.arbitrary,+        TimeConstDatetime <$> nonNegativeMaybeInt64 <*> Qc.arbitrary+      ]+    where+      nonNegativeMaybeInt64 = Qc.oneof [pure Nothing, Just <$> nonNegativeInt64]+      nonNegativeInt64 = Qc.sized (\n -> Qc.choose (0, cap n))+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/ConstTypename.hs view
@@ -0,0 +1,49 @@+module PostgresqlSyntax.Ast.ConstTypename where++import PostgresqlSyntax.Ast.Bit (Bit)+import PostgresqlSyntax.Ast.ConstCharacter+import PostgresqlSyntax.Ast.ConstDatetime+import PostgresqlSyntax.Ast.Numeric+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- ConstTypename:+--   | Numeric+--   | ConstBit+--   | ConstCharacter+--   | ConstDatetime+-- @+data ConstTypename+  = NumericConstTypename Numeric+  | ConstBitConstTypename Bit+  | ConstCharacterConstTypename ConstCharacter+  | ConstDatetimeConstTypename ConstDatetime+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ConstTypename where+  toTextBuilder settings = \case+    NumericConstTypename a -> toTextBuilder settings a+    ConstBitConstTypename a -> toTextBuilder settings a+    ConstCharacterConstTypename a -> toTextBuilder settings a+    ConstDatetimeConstTypename a -> toTextBuilder settings a+  parser settings =+    asum+      [ NumericConstTypename <$> parser settings,+        ConstBitConstTypename <$> parser settings,+        ConstCharacterConstTypename <$> parser settings,+        ConstDatetimeConstTypename <$> parser settings+      ]++instance Qc.Arbitrary ConstTypename where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ NumericConstTypename <$> Qc.arbitrary,+        ConstBitConstTypename <$> Qc.arbitrary,+        ConstCharacterConstTypename <$> Qc.arbitrary,+        ConstDatetimeConstTypename <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/DeleteStmt.hs view
@@ -0,0 +1,56 @@+module PostgresqlSyntax.Ast.DeleteStmt where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.RelationExprOptAlias (RelationExprOptAlias)+import qualified PostgresqlSyntax.Ast.RelationExprOptAlias as RelationExprOptAlias+import PostgresqlSyntax.Ast.ReturningClause+import PostgresqlSyntax.Ast.UsingClause+import PostgresqlSyntax.Ast.WhereOrCurrentClause+import {-# SOURCE #-} PostgresqlSyntax.Ast.WithClause (WithClause)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- DeleteStmt:+--   | opt_with_clause DELETE_P FROM relation_expr_opt_alias+--       using_clause where_or_current_clause returning_clause+-- @+data DeleteStmt = DeleteStmt (Maybe WithClause) RelationExprOptAlias (Maybe UsingClause) (Maybe WhereOrCurrentClause) (Maybe ReturningClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst DeleteStmt where+  toTextBuilder settings (DeleteStmt a b c d e) =+    TextBuilders.prefixMaybe (toTextBuilder settings) a+      <> "DELETE FROM "+      <> toTextBuilder settings b+      <> TextBuilders.suffixMaybe (toTextBuilder settings) c+      <> TextBuilders.suffixMaybe (toTextBuilder settings) d+      <> TextBuilders.suffixMaybe (toTextBuilder settings) e+  parser settings = do+    a <- optional (Parser.wrapToHead (parser settings) <* Parsers.space1)+    Parsers.keyword "delete"+    Parsers.space1+    Parser.endHead+    Parsers.keyword "from"+    Parsers.space1+    b <- RelationExprOptAlias.customizedParser settings ["using", "where", "returning"]+    c <- optional (Parsers.space1 *> parser settings)+    d <- optional (Parsers.space1 *> parser settings)+    e <- optional (Parsers.space1 *> parser settings)+    return (DeleteStmt a b c d e)++instance Qc.Arbitrary DeleteStmt where+  shrink = Qc.genericShrink+  arbitrary =+    DeleteStmt+      <$> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)+      <*> Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/ExplicitRow.hs view
@@ -0,0 +1,41 @@+module PostgresqlSyntax.Ast.ExplicitRow where++import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- explicit_row:+--   | ROW '(' expr_list ')'+--   | ROW '(' ')'+-- @+data ExplicitRow+  = EmptyExplicitRow+  | ExprListExplicitRow ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ExplicitRow where+  toTextBuilder settings a =+    "ROW "+      <> TextBuilders.renderInParens+        ( case a of+            EmptyExplicitRow -> mempty+            ExprListExplicitRow b -> toTextBuilder settings b+        )+  parser settings =+    Parsers.keyword "row"+      *> Parsers.space+      *> Parsers.inParens (maybe EmptyExplicitRow ExprListExplicitRow <$> optional (parser settings))++instance Qc.Arbitrary ExplicitRow where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure EmptyExplicitRow,+        ExprListExplicitRow <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/ExprList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.ExprList where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- expr_list:+--   | a_expr+--   | expr_list ',' a_expr+-- @+newtype ExprList = ExprList (NonEmpty AExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ExprList where+  toTextBuilder settings (ExprList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = ExprList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary ExprList where+  shrink = Qc.genericShrink+  arbitrary = ExprList <$> Gens.nonEmptyUpTo 6 (Gens.downscale Qc.arbitrary)
+ library-internal/PostgresqlSyntax/Ast/ExtractArg.hs view
@@ -0,0 +1,68 @@+module PostgresqlSyntax.Ast.ExtractArg where++import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Sconst+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- extract_arg:+--   | IDENT+--   | YEAR_P+--   | MONTH_P+--   | DAY_P+--   | HOUR_P+--   | MINUTE_P+--   | SECOND_P+--   | Sconst+-- @+data ExtractArg+  = IdentExtractArg Ident+  | YearExtractArg+  | MonthExtractArg+  | DayExtractArg+  | HourExtractArg+  | MinuteExtractArg+  | SecondExtractArg+  | SconstExtractArg Sconst+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ExtractArg where+  toTextBuilder settings = \case+    IdentExtractArg a -> toTextBuilder settings a+    YearExtractArg -> "YEAR"+    MonthExtractArg -> "MONTH"+    DayExtractArg -> "DAY"+    HourExtractArg -> "HOUR"+    MinuteExtractArg -> "MINUTE"+    SecondExtractArg -> "SECOND"+    SconstExtractArg a -> toTextBuilder settings a+  parser settings =+    asum+      [ YearExtractArg <$ Parsers.keyword "year",+        MonthExtractArg <$ Parsers.keyword "month",+        DayExtractArg <$ Parsers.keyword "day",+        HourExtractArg <$ Parsers.keyword "hour",+        MinuteExtractArg <$ Parsers.keyword "minute",+        SecondExtractArg <$ Parsers.keyword "second",+        SconstExtractArg <$> parser settings,+        IdentExtractArg <$> parser settings+      ]++instance Qc.Arbitrary ExtractArg where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ IdentExtractArg <$> Qc.arbitrary,+        pure YearExtractArg,+        pure MonthExtractArg,+        pure DayExtractArg,+        pure HourExtractArg,+        pure MinuteExtractArg,+        pure SecondExtractArg,+        SconstExtractArg <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/ExtractList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.ExtractList where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExtractArg+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- extract_list:+--   | extract_arg FROM a_expr+--   | EMPTY+-- @+data ExtractList = ExtractList ExtractArg AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ExtractList where+  toTextBuilder settings (ExtractList a b) = toTextBuilder settings a <> " FROM " <> toTextBuilder settings b+  parser settings = ExtractList <$> parser settings <*> (Parsers.space1 *> Parsers.keyword "from" *> Parsers.space1 *> parser settings)++instance Qc.Arbitrary ExtractList where+  shrink = Qc.genericShrink+  arbitrary = ExtractList <$> arbitrary <*> Gens.downscale arbitrary
+ library-internal/PostgresqlSyntax/Ast/Fconst.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.Fconst where++import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- FCONST+-- @+newtype Fconst = Fconst Double+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Fconst where+  toTextBuilder _settings (Fconst a) = TextBuilder.doubleDec a+  parser _settings = Fconst <$> Parsers.float++instance Qc.Arbitrary Fconst where+  shrink = Qc.genericShrink++  -- Parsed via 'Parsers.float' (unsigned — the sign, when present, is a+  -- separate unary @AExpr@\/@BExpr@ operator applied outside this type), so+  -- it must never be negative, mirroring+  -- 'PostgresqlSyntax.Ast.IntervalSecond'\'s own @nonNegative@.+  arbitrary =+    Fconst . abs+      <$> (Qc.arbitrary `Qc.suchThat` (\a -> fromIntegral (round a :: Int) /= a))
+ library-internal/PostgresqlSyntax/Ast/ForLockingClause.hs view
@@ -0,0 +1,41 @@+module PostgresqlSyntax.Ast.ForLockingClause where++import PostgresqlSyntax.Ast.ForLockingItem+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- for_locking_clause:+--   | for_locking_items+--   | FOR READ ONLY+-- for_locking_items:+--   | for_locking_item+--   | for_locking_items for_locking_item+-- @+data ForLockingClause+  = ItemsForLockingClause (NonEmpty ForLockingItem)+  | ReadOnlyForLockingClause+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ForLockingClause where+  toTextBuilder settings = \case+    ItemsForLockingClause a -> TextBuilders.spaceNonEmpty (toTextBuilder settings) a+    ReadOnlyForLockingClause -> "FOR READ ONLY"+  parser settings = readOnly <|> items+    where+      readOnly = ReadOnlyForLockingClause <$ Parsers.keyphrase "for read only"+      items = ItemsForLockingClause <$> Parsers.sep1 Parsers.space1 (parser settings)++instance Qc.Arbitrary ForLockingClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ItemsForLockingClause <$> Gens.nonEmptyUpTo 7 Qc.arbitrary,+        pure ReadOnlyForLockingClause+      ]
+ library-internal/PostgresqlSyntax/Ast/ForLockingItem.hs view
@@ -0,0 +1,49 @@+module PostgresqlSyntax.Ast.ForLockingItem where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ForLockingStrength+import PostgresqlSyntax.Ast.QualifiedName+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- for_locking_item:+--   | for_locking_strength locked_rels_list opt_nowait_or_skip+-- locked_rels_list:+--   | OF qualified_name_list+--   | EMPTY+-- opt_nowait_or_skip:+--   | NOWAIT+--   | SKIP LOCKED+--   | EMPTY+-- @+data ForLockingItem = ForLockingItem ForLockingStrength (Maybe (NonEmpty QualifiedName)) (Maybe Bool)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ForLockingItem where+  toTextBuilder settings (ForLockingItem a b c) =+    TextBuilders.optLexemes+      [ Just (toTextBuilder settings a),+        fmap lockedRelsList b,+        fmap nowaitOrSkip c+      ]+    where+      lockedRelsList a' = "OF " <> TextBuilders.commaNonEmpty (toTextBuilder settings) a'+      nowaitOrSkip = bool "NOWAIT" "SKIP LOCKED"+  parser settings = do+    strength <- parser settings+    rels <- optional $ Parsers.space1 *> Parsers.keyword "of" *> Parsers.space1 *> Parser.endHead *> Parsers.sep1 Parsers.commaSeparator (parser settings)+    nowaitOrSkip <- optional (Parsers.space1 *> nowaitOrSkip)+    return (ForLockingItem strength rels nowaitOrSkip)+    where+      nowaitOrSkip = False <$ Parsers.keyword "nowait" <|> True <$ Parsers.keyphrase "skip locked"++instance Qc.Arbitrary ForLockingItem where+  shrink = Qc.genericShrink+  arbitrary = ForLockingItem <$> arbitrary <*> Gens.terminatingMaybe arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/ForLockingStrength.hs view
@@ -0,0 +1,48 @@+module PostgresqlSyntax.Ast.ForLockingStrength where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- for_locking_strength:+--   | FOR UPDATE+--   | FOR NO KEY UPDATE+--   | FOR SHARE+--   | FOR KEY SHARE+-- @+data ForLockingStrength+  = UpdateForLockingStrength+  | NoKeyUpdateForLockingStrength+  | ShareForLockingStrength+  | KeyForLockingStrength+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ForLockingStrength where+  toTextBuilder _settings = \case+    UpdateForLockingStrength -> "FOR UPDATE"+    NoKeyUpdateForLockingStrength -> "FOR NO KEY UPDATE"+    ShareForLockingStrength -> "FOR SHARE"+    KeyForLockingStrength -> "FOR KEY SHARE"+  parser _settings =+    UpdateForLockingStrength+      <$ Parsers.keyphrase "for update"+        <|> NoKeyUpdateForLockingStrength+      <$ Parsers.keyphrase "for no key update"+        <|> ShareForLockingStrength+      <$ Parsers.keyphrase "for share"+        <|> KeyForLockingStrength+      <$ Parsers.keyphrase "for key share"++instance Qc.Arbitrary ForLockingStrength where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.elements+      [ UpdateForLockingStrength,+        NoKeyUpdateForLockingStrength,+        ShareForLockingStrength,+        KeyForLockingStrength+      ]
+ library-internal/PostgresqlSyntax/Ast/FrameBound.hs view
@@ -0,0 +1,56 @@+module PostgresqlSyntax.Ast.FrameBound where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- frame_bound:+--   |  UNBOUNDED PRECEDING+--   |  UNBOUNDED FOLLOWING+--   |  CURRENT_P ROW+--   |  a_expr PRECEDING+--   |  a_expr FOLLOWING+-- @+data FrameBound+  = UnboundedPrecedingFrameBound+  | UnboundedFollowingFrameBound+  | CurrentRowFrameBound+  | PrecedingFrameBound AExpr+  | FollowingFrameBound AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FrameBound where+  toTextBuilder settings = \case+    UnboundedPrecedingFrameBound -> "UNBOUNDED PRECEDING"+    UnboundedFollowingFrameBound -> "UNBOUNDED FOLLOWING"+    CurrentRowFrameBound -> "CURRENT ROW"+    PrecedingFrameBound a -> toTextBuilder settings a <> " PRECEDING"+    FollowingFrameBound a -> toTextBuilder settings a <> " FOLLOWING"+  parser settings =+    UnboundedPrecedingFrameBound+      <$ Parsers.keyphrase "unbounded preceding"+        <|> UnboundedFollowingFrameBound+      <$ Parsers.keyphrase "unbounded following"+        <|> CurrentRowFrameBound+      <$ Parsers.keyphrase "current row"+        <|> do+          a <- parser settings :: Parser AExpr+          Parsers.space1+          PrecedingFrameBound a <$ Parsers.keyword "preceding" <|> FollowingFrameBound a <$ Parsers.keyword "following"++instance Qc.Arbitrary FrameBound where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure UnboundedPrecedingFrameBound,+        pure UnboundedFollowingFrameBound,+        pure CurrentRowFrameBound,+        PrecedingFrameBound <$> Gens.downscale Qc.arbitrary,+        FollowingFrameBound <$> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FrameClause.hs view
@@ -0,0 +1,40 @@+module PostgresqlSyntax.Ast.FrameClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FrameClauseMode+import PostgresqlSyntax.Ast.FrameExtent+import PostgresqlSyntax.Ast.WindowExclusionClause+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_frame_clause:+--   |  RANGE frame_extent opt_window_exclusion_clause+--   |  ROWS frame_extent opt_window_exclusion_clause+--   |  GROUPS frame_extent opt_window_exclusion_clause+--   |  EMPTY+-- @+data FrameClause = FrameClause FrameClauseMode FrameExtent (Maybe WindowExclusionClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FrameClause where+  toTextBuilder settings (FrameClause a b c) =+    TextBuilders.optLexemes+      [ Just (toTextBuilder settings a),+        Just (toTextBuilder settings b),+        fmap (toTextBuilder settings) c+      ]+  parser settings = do+    a <- parser settings <* Parsers.space1 <* Parser.endHead+    b <- parser settings+    c <- optional (Parsers.space1 *> parser settings)+    return (FrameClause a b c)++instance Qc.Arbitrary FrameClause where+  shrink = Qc.genericShrink+  arbitrary = FrameClause <$> arbitrary <*> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/FrameClauseMode.hs view
@@ -0,0 +1,34 @@+module PostgresqlSyntax.Ast.FrameClauseMode where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_frame_clause:+--   |  RANGE frame_extent opt_window_exclusion_clause+--   |  ROWS frame_extent opt_window_exclusion_clause+--   |  GROUPS frame_extent opt_window_exclusion_clause+--   |  EMPTY+-- @+data FrameClauseMode = RangeFrameClauseMode | RowsFrameClauseMode | GroupsFrameClauseMode+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FrameClauseMode where+  toTextBuilder _settings = \case+    RangeFrameClauseMode -> "RANGE"+    RowsFrameClauseMode -> "ROWS"+    GroupsFrameClauseMode -> "GROUPS"+  parser _settings =+    asum+      [ RangeFrameClauseMode <$ Parsers.keyword "range",+        RowsFrameClauseMode <$ Parsers.keyword "rows",+        GroupsFrameClauseMode <$ Parsers.keyword "groups"+      ]++instance Qc.Arbitrary FrameClauseMode where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [RangeFrameClauseMode, RowsFrameClauseMode, GroupsFrameClauseMode]
+ library-internal/PostgresqlSyntax/Ast/FrameExtent.hs view
@@ -0,0 +1,37 @@+module PostgresqlSyntax.Ast.FrameExtent where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FrameBound+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- frame_extent:+--   |  frame_bound+--   |  BETWEEN frame_bound AND frame_bound+-- @+data FrameExtent = SingularFrameExtent FrameBound | BetweenFrameExtent FrameBound FrameBound+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FrameExtent where+  toTextBuilder settings = \case+    SingularFrameExtent a -> toTextBuilder settings a+    BetweenFrameExtent a b -> "BETWEEN " <> toTextBuilder settings a <> " AND " <> toTextBuilder settings b+  parser settings =+    BetweenFrameExtent+      <$> (Parsers.keyword "between" *> Parsers.space1 *> Parser.endHead *> parser settings <* Parsers.space1 <* Parsers.keyword "and" <* Parsers.space1)+      <*> parser settings+        <|> SingularFrameExtent+      <$> parser settings++instance Qc.Arbitrary FrameExtent where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ SingularFrameExtent <$> Qc.arbitrary,+        BetweenFrameExtent <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FromClause.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.FromClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FromList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- from_clause:+--   |  FROM from_list+--   |  /*EMPTY*/+-- @+newtype FromClause = FromClause FromList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FromClause where+  toTextBuilder settings (FromClause a) = "FROM " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "from"+    Parser.endHead+    Parsers.space1+    FromClause <$> parser settings++instance Qc.Arbitrary FromClause where+  shrink = Qc.genericShrink+  arbitrary = FromClause <$> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/FromList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.FromList where++import PostgresqlSyntax.Ast.TableRef+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- from_list:+--   |  table_ref+--   |  from_list ',' table_ref+-- @+newtype FromList = FromList (NonEmpty TableRef)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FromList where+  toTextBuilder settings (FromList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = FromList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary FromList where+  shrink = Qc.genericShrink+  arbitrary = FromList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/FuncAliasClause.hs view
@@ -0,0 +1,83 @@+module PostgresqlSyntax.Ast.FuncAliasClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AliasClause+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.TableFuncElementList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_alias_clause:+--   | alias_clause+--   | AS '(' TableFuncElementList ')'+--   | AS ColId '(' TableFuncElementList ')'+--   | ColId '(' TableFuncElementList ')'+--   | EMPTY+-- @+data FuncAliasClause+  = AliasFuncAliasClause AliasClause+  | AsFuncAliasClause TableFuncElementList+  | AsColIdFuncAliasClause Ident TableFuncElementList+  | ColIdFuncAliasClause Ident TableFuncElementList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncAliasClause where+  toTextBuilder settings = \case+    AliasFuncAliasClause a -> toTextBuilder settings a+    AsFuncAliasClause a -> "AS (" <> toTextBuilder settings a <> ")"+    AsColIdFuncAliasClause a b -> "AS " <> toTextBuilder settings a <> " (" <> toTextBuilder settings b <> ")"+    ColIdFuncAliasClause a b -> toTextBuilder settings a <> " (" <> toTextBuilder settings b <> ")"+  parser settings =+    asum+      [ do+          _ <- Parsers.keyword "as"+          asum+            [ do+                Parsers.space+                Parsers.inParens $ do+                  Parser.endHead+                  AsFuncAliasClause <$> parser settings,+              do+                Parsers.space1+                a <- colId settings+                asum+                  [ do+                      Parsers.space+                      Parsers.inParens $ do+                        Parser.endHead+                        asum+                          [ AsColIdFuncAliasClause a <$> Parser.wrapToHead (parser settings),+                            AliasFuncAliasClause . AliasClause True a . Just <$> parser settings+                          ],+                    pure (AliasFuncAliasClause (AliasClause True a Nothing))+                  ]+            ],+        do+          a <- colId settings+          asum+            [ do+                Parsers.space+                Parsers.inParens $ do+                  Parser.endHead+                  asum+                    [ ColIdFuncAliasClause a <$> Parser.wrapToHead (parser settings),+                      AliasFuncAliasClause . AliasClause False a . Just <$> parser settings+                    ],+              pure (AliasFuncAliasClause (AliasClause False a Nothing))+            ]+      ]++instance Qc.Arbitrary FuncAliasClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ AliasFuncAliasClause <$> Qc.arbitrary,+        AsFuncAliasClause <$> Qc.arbitrary,+        AsColIdFuncAliasClause <$> Qc.arbitrary <*> Qc.arbitrary,+        ColIdFuncAliasClause <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FuncApplication.hs view
@@ -0,0 +1,39 @@+module PostgresqlSyntax.Ast.FuncApplication where++import PostgresqlSyntax.Ast.FuncApplicationParams+import PostgresqlSyntax.Ast.FuncName+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_application:+--   |  func_name '(' ')'+--   |  func_name '(' func_arg_list opt_sort_clause ')'+--   |  func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'+--   |  func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')'+--   |  func_name '(' ALL func_arg_list opt_sort_clause ')'+--   |  func_name '(' DISTINCT func_arg_list opt_sort_clause ')'+--   |  func_name '(' '*' ')'+-- @+data FuncApplication = FuncApplication FuncName (Maybe FuncApplicationParams)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncApplication where+  toTextBuilder settings (FuncApplication a b) = toTextBuilder settings a <> "(" <> foldMap (toTextBuilder settings) b <> ")"++  -- \"operator\" immediately followed by \"(\" is always parsed as the start+  -- of a qualified operator (@OPERATOR(...)@), never as a call to a function+  -- literally named \"operator\", mirroring how real PostgreSQL's grammar+  -- resolves the conflict between these two productions in favor of qual_op.+  parser settings =+    Parsers.notFollowedBy (Parsers.keyword "operator" *> Parsers.space *> Parsers.char '(')+      *> Parsers.inParensWithLabel FuncApplication (parser settings) (optional (parser settings))++instance Qc.Arbitrary FuncApplication where+  shrink = Qc.genericShrink+  arbitrary = FuncApplication <$> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/FuncApplicationParams.hs view
@@ -0,0 +1,111 @@+module PostgresqlSyntax.Ast.FuncApplicationParams where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FuncArgExpr+import PostgresqlSyntax.Ast.SortClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_application:+--   |  func_name '(' ')'+--   |  func_name '(' func_arg_list opt_sort_clause ')'+--   |  func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'+--   |  func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')'+--   |  func_name '(' ALL func_arg_list opt_sort_clause ')'+--   |  func_name '(' DISTINCT func_arg_list opt_sort_clause ')'+--   |  func_name '(' '*' ')'+-- @+data FuncApplicationParams+  = NormalFuncApplicationParams (Maybe Bool) (NonEmpty FuncArgExpr) (Maybe SortClause)+  | VariadicFuncApplicationParams (Maybe (NonEmpty FuncArgExpr)) FuncArgExpr (Maybe SortClause)+  | StarFuncApplicationParams+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncApplicationParams where+  toTextBuilder settings = \case+    NormalFuncApplicationParams a b c ->+      TextBuilders.optLexemes+        [ fmap TextBuilders.renderAllOrDistinct a,+          Just (TextBuilders.commaNonEmpty (toTextBuilder settings) b),+          fmap (toTextBuilder settings) c+        ]+    VariadicFuncApplicationParams a b c ->+      TextBuilders.optLexemes+        [ fmap (flip mappend "," . TextBuilders.commaNonEmpty (toTextBuilder settings)) a,+          Just "VARIADIC",+          Just (toTextBuilder settings b),+          fmap (toTextBuilder settings) c+        ]+    StarFuncApplicationParams -> "*"+  parser settings =+    asum+      [ starFuncApplicationParams,+        listVariadicFuncApplicationParams,+        singleVariadicFuncApplicationParams,+        normalFuncApplicationParams+      ]+    where+      normalFuncApplicationParams = do+        optAllOrDistinct <- optional (Parsers.allOrDistinct <* Parsers.space1)+        argList <- Parsers.sep1 Parsers.commaSeparator (parser settings)+        Parser.endHead+        optSortClause <- optional (Parsers.space1 *> parser settings)+        return (NormalFuncApplicationParams optAllOrDistinct argList optSortClause)+      singleVariadicFuncApplicationParams = do+        Parsers.keyword "variadic"+        Parsers.space1+        Parser.endHead+        arg <- parser settings+        optSortClause <- optional (Parsers.space1 *> parser settings)+        return (VariadicFuncApplicationParams Nothing arg optSortClause)++      -- @func_arg_list ',' VARIADIC func_arg_expr@: one or more+      -- comma-separated 'FuncArgExpr's, where the final comma is+      -- immediately followed by (and the @VARIADIC@ Parsers.keyword itself consumed+      -- by) the terminating branch — equivalent to the pre-extraction+      -- @sepEnd1 Parsers.commaSeparator (Parsers.keyword "variadic" <* space1) funcArgExpr@.+      listVariadicFuncApplicationParams = do+        argList <- Parser.wrapToHead argListEndingInVariadic+        Parser.endHead+        arg <- parser settings+        optSortClause <- optional (Parsers.space1 *> parser settings)+        return (VariadicFuncApplicationParams (Just argList) arg optSortClause)+      argListEndingInVariadic = do+        a <- parser settings+        Parsers.commaSeparator+        asum+          [ pure (a :| []) <* (Parsers.keyword "variadic" *> Parsers.space1),+            (\(b :| bs) -> a :| b : bs) <$> argListEndingInVariadic+          ]+      -- A bare '*' char can also be the leading char of a longer operator+      -- token (e.g. "*#" in @foo(*# DEFAULT)@'s @PrefixQualOpAExpr@), so+      -- this only commits to the wildcard reading when no further op char+      -- follows — otherwise it falls through to 'normalFuncApplicationParams',+      -- which parses the '*' as the start of that operator instead.+      starFuncApplicationParams =+        Parsers.space+          *> Parsers.char '*'+          *> Parsers.notFollowedBy (Parsers.satisfy Predicate.opChar)+          *> Parser.endHead+          *> Parsers.space+            $> StarFuncApplicationParams++instance Qc.Arbitrary FuncApplicationParams where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ NormalFuncApplicationParams <$> Qc.arbitrary <*> nonEmptyOf 8 <*> Gens.terminatingMaybe Qc.arbitrary,+        VariadicFuncApplicationParams <$> maybeNonEmptyOf 8 <*> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary,+        pure StarFuncApplicationParams+      ]+    where+      nonEmptyOf hi = Gens.nonEmptyUpTo (hi - 1) Qc.arbitrary+      maybeNonEmptyOf hi = Qc.oneof [pure Nothing, Just <$> nonEmptyOf hi]
+ library-internal/PostgresqlSyntax/Ast/FuncArgExpr.hs view
@@ -0,0 +1,70 @@+module PostgresqlSyntax.Ast.FuncArgExpr where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_arg_expr:+--   | a_expr+--   | param_name COLON_EQUALS a_expr+--   | param_name EQUALS_GREATER a_expr+-- param_name:+--   | type_function_name+-- @+data FuncArgExpr+  = ExprFuncArgExpr AExpr+  | ColonEqualsFuncArgExpr Ident AExpr+  | EqualsGreaterFuncArgExpr Ident AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncArgExpr where+  toTextBuilder settings = \case+    ExprFuncArgExpr a -> toTextBuilder settings a+    ColonEqualsFuncArgExpr a b -> toTextBuilder settings a <> " := " <> toTextBuilder settings b+    EqualsGreaterFuncArgExpr a b -> toTextBuilder settings a <> " => " <> toTextBuilder settings b+  parser settings =+    asum+      [ do+          a <- Parser.wrapToHead typeFunctionName+          Parsers.space+          asum+            [ do+                Parsers.string ":="+                Parser.endHead+                b <- Parsers.space *> parser settings+                return (ColonEqualsFuncArgExpr a b),+              do+                Parsers.string "=>"+                Parser.endHead+                b <- Parsers.space *> parser settings+                return (EqualsGreaterFuncArgExpr a b)+            ],+        ExprFuncArgExpr <$> parser settings+      ]+    where+      -- Duplicated from "PostgresqlSyntax.Parsing"'s @typeFunctionName@+      -- (a bare-aliased 'PostgresqlSyntax.Ast.Ident' whose own parser lives+      -- above this module in the dependency order), mirroring the+      -- 'PostgresqlSyntax.Ast.AnyName'\/'PostgresqlSyntax.Ast.NameList'+      -- precedent.+      typeFunctionName =+        Parsers.keywordNameFromSet UnquotedIdent KeywordSet.typeFunctionName+          <|> parser settings++instance Qc.Arbitrary FuncArgExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprFuncArgExpr <$> Gens.downscale Qc.arbitrary,+        ColonEqualsFuncArgExpr <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+        EqualsGreaterFuncArgExpr <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FuncConstArgs.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.FuncConstArgs where++import PostgresqlSyntax.Ast.FuncArgExpr+import PostgresqlSyntax.Ast.SortClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- The parenthesized-argument-list part of a @func_name '(' func_arg_list+-- opt_sort_clause ')' Sconst@ 'PostgresqlSyntax.Ast.AexprConst' — rendered\/+-- parsed without its enclosing parens, which belong to the caller.+--+-- ==== References+-- @+--   |  func_name '(' func_arg_list opt_sort_clause ')' Sconst+-- @+data FuncConstArgs = FuncConstArgs (NonEmpty FuncArgExpr) (Maybe SortClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncConstArgs where+  toTextBuilder settings (FuncConstArgs a b) = TextBuilders.commaNonEmpty (toTextBuilder settings) a <> TextBuilders.suffixMaybe (toTextBuilder settings) b+  parser settings = FuncConstArgs <$> Parsers.sep1 Parsers.commaSeparator (parser settings) <*> optional (Parsers.space1 *> parser settings)++instance Qc.Arbitrary FuncConstArgs where+  shrink = Qc.genericShrink+  arbitrary = FuncConstArgs <$> Gens.nonEmptyUpTo 6 Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/FuncExpr.hs view
@@ -0,0 +1,78 @@+module PostgresqlSyntax.Ast.FuncExpr where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.FuncApplication+import PostgresqlSyntax.Ast.FuncExprCommonSubexpr+import PostgresqlSyntax.Ast.OverClause+import PostgresqlSyntax.Ast.SortClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_expr:+--   | func_application within_group_clause filter_clause over_clause+--   | func_expr_common_subexpr+-- @+--+-- @within_group_clause@ and @filter_clause@ are bare aliases to+-- 'PostgresqlSyntax.Ast.SortClause' and 'PostgresqlSyntax.Ast.AExpr'+-- respectively.+data FuncExpr+  = ApplicationFuncExpr FuncApplication (Maybe SortClause) (Maybe AExpr) (Maybe OverClause)+  | SubexprFuncExpr FuncExprCommonSubexpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncExpr where+  toTextBuilder settings = \case+    ApplicationFuncExpr a b c d ->+      TextBuilders.optLexemes+        [ Just (toTextBuilder settings a),+          fmap withinGroupClause b,+          fmap filterClause c,+          fmap (toTextBuilder settings) d+        ]+    SubexprFuncExpr a -> toTextBuilder settings a+    where+      withinGroupClause a = "WITHIN GROUP (" <> toTextBuilder settings a <> ")"+      filterClause a = "FILTER (WHERE " <> toTextBuilder settings a <> ")"+  parser settings =+    asum+      [ SubexprFuncExpr <$> parser settings,+        do+          a <- parser settings+          Parser.endHead+          b <- optional (Parsers.space1 *> withinGroupClause)+          c <- optional (Parsers.space1 *> filterClause)+          d <- optional (Parsers.space1 *> parser settings)+          return (ApplicationFuncExpr a b c d)+      ]+    where+      withinGroupClause = do+        Parsers.keyphrase "within group"+        Parser.endHead+        Parsers.space+        Parsers.inParens (parser settings)+      filterClause = do+        Parsers.keyword "filter"+        Parser.endHead+        Parsers.space+        Parsers.inParens (Parsers.keyword "where" *> Parsers.space1 *> parser settings)++instance Qc.Arbitrary FuncExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ApplicationFuncExpr+          <$> Qc.arbitrary+          <*> Gens.terminatingMaybe Qc.arbitrary+          <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)+          <*> Gens.terminatingMaybe Qc.arbitrary,+        SubexprFuncExpr <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FuncExprCommonSubexpr.hs view
@@ -0,0 +1,199 @@+module PostgresqlSyntax.Ast.FuncExprCommonSubexpr where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.ExtractList+import PostgresqlSyntax.Ast.OverlayList+import PostgresqlSyntax.Ast.PositionList+import PostgresqlSyntax.Ast.SubstrList+import PostgresqlSyntax.Ast.TrimList+import PostgresqlSyntax.Ast.TrimModifier+import PostgresqlSyntax.Ast.Typename+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_expr_common_subexpr:+--   | COLLATION FOR '(' a_expr ')'+--   | CURRENT_DATE+--   | CURRENT_TIME+--   | CURRENT_TIME '(' Iconst ')'+--   | CURRENT_TIMESTAMP+--   | CURRENT_TIMESTAMP '(' Iconst ')'+--   | LOCALTIME+--   | LOCALTIME '(' Iconst ')'+--   | LOCALTIMESTAMP+--   | LOCALTIMESTAMP '(' Iconst ')'+--   | CURRENT_ROLE+--   | CURRENT_USER+--   | SESSION_USER+--   | USER+--   | CURRENT_CATALOG+--   | CURRENT_SCHEMA+--   | CAST '(' a_expr AS Typename ')'+--   | EXTRACT '(' extract_list ')'+--   | OVERLAY '(' overlay_list ')'+--   | POSITION '(' position_list ')'+--   | SUBSTRING '(' substr_list ')'+--   | TREAT '(' a_expr AS Typename ')'+--   | TRIM '(' BOTH trim_list ')'+--   | TRIM '(' LEADING trim_list ')'+--   | TRIM '(' TRAILING trim_list ')'+--   | TRIM '(' trim_list ')'+--   | NULLIF '(' a_expr ',' a_expr ')'+--   | COALESCE '(' expr_list ')'+--   | GREATEST '(' expr_list ')'+--   | LEAST '(' expr_list ')'+--   | XMLCONCAT '(' expr_list ')'+--   | XMLELEMENT '(' NAME_P ColLabel ')'+--   | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'+--   | XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'+--   | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'+--   | XMLEXISTS '(' c_expr xmlexists_argument ')'+--   | XMLFOREST '(' xml_attribute_list ')'+--   | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'+--   | XMLPI '(' NAME_P ColLabel ')'+--   | XMLPI '(' NAME_P ColLabel ',' a_expr ')'+--   | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'+--   | XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'+--+-- TODO: Implement the XML cases+-- @+data FuncExprCommonSubexpr+  = CollationForFuncExprCommonSubexpr AExpr+  | CurrentDateFuncExprCommonSubexpr+  | CurrentTimeFuncExprCommonSubexpr (Maybe Int64)+  | CurrentTimestampFuncExprCommonSubexpr (Maybe Int64)+  | LocalTimeFuncExprCommonSubexpr (Maybe Int64)+  | LocalTimestampFuncExprCommonSubexpr (Maybe Int64)+  | CurrentRoleFuncExprCommonSubexpr+  | CurrentUserFuncExprCommonSubexpr+  | SessionUserFuncExprCommonSubexpr+  | UserFuncExprCommonSubexpr+  | CurrentCatalogFuncExprCommonSubexpr+  | CurrentSchemaFuncExprCommonSubexpr+  | CastFuncExprCommonSubexpr AExpr Typename+  | ExtractFuncExprCommonSubexpr (Maybe ExtractList)+  | OverlayFuncExprCommonSubexpr OverlayList+  | PositionFuncExprCommonSubexpr (Maybe PositionList)+  | SubstringFuncExprCommonSubexpr (Maybe SubstrList)+  | TreatFuncExprCommonSubexpr AExpr Typename+  | TrimFuncExprCommonSubexpr (Maybe TrimModifier) TrimList+  | NullIfFuncExprCommonSubexpr AExpr AExpr+  | CoalesceFuncExprCommonSubexpr ExprList+  | GreatestFuncExprCommonSubexpr ExprList+  | LeastFuncExprCommonSubexpr ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncExprCommonSubexpr where+  toTextBuilder settings = \case+    CollationForFuncExprCommonSubexpr a -> "COLLATION FOR (" <> toTextBuilder settings a <> ")"+    CurrentDateFuncExprCommonSubexpr -> "CURRENT_DATE"+    CurrentTimeFuncExprCommonSubexpr a -> "CURRENT_TIME" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) a+    CurrentTimestampFuncExprCommonSubexpr a -> "CURRENT_TIMESTAMP" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) a+    LocalTimeFuncExprCommonSubexpr a -> "LOCALTIME" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) a+    LocalTimestampFuncExprCommonSubexpr a -> "LOCALTIMESTAMP" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) a+    CurrentRoleFuncExprCommonSubexpr -> "CURRENT_ROLE"+    CurrentUserFuncExprCommonSubexpr -> "CURRENT_USER"+    SessionUserFuncExprCommonSubexpr -> "SESSION_USER"+    UserFuncExprCommonSubexpr -> "USER"+    CurrentCatalogFuncExprCommonSubexpr -> "CURRENT_CATALOG"+    CurrentSchemaFuncExprCommonSubexpr -> "CURRENT_SCHEMA"+    CastFuncExprCommonSubexpr a b -> "CAST (" <> toTextBuilder settings a <> " AS " <> toTextBuilder settings b <> ")"+    ExtractFuncExprCommonSubexpr a -> "EXTRACT (" <> foldMap (toTextBuilder settings) a <> ")"+    OverlayFuncExprCommonSubexpr a -> "OVERLAY (" <> toTextBuilder settings a <> ")"+    PositionFuncExprCommonSubexpr a -> "POSITION (" <> foldMap (toTextBuilder settings) a <> ")"+    SubstringFuncExprCommonSubexpr a -> "SUBSTRING (" <> foldMap (toTextBuilder settings) a <> ")"+    TreatFuncExprCommonSubexpr a b -> "TREAT (" <> toTextBuilder settings a <> " AS " <> toTextBuilder settings b <> ")"+    TrimFuncExprCommonSubexpr a b -> "TRIM (" <> TextBuilders.prefixMaybe (toTextBuilder settings) a <> toTextBuilder settings b <> ")"+    NullIfFuncExprCommonSubexpr a b -> "NULLIF (" <> toTextBuilder settings a <> ", " <> toTextBuilder settings b <> ")"+    CoalesceFuncExprCommonSubexpr a -> "COALESCE (" <> toTextBuilder settings a <> ")"+    GreatestFuncExprCommonSubexpr a -> "GREATEST (" <> toTextBuilder settings a <> ")"+    LeastFuncExprCommonSubexpr a -> "LEAST (" <> toTextBuilder settings a <> ")"+  parser settings =+    asum+      [ CollationForFuncExprCommonSubexpr <$> Parsers.inParensWithClause (Parsers.keyphrase "collation for") (parser settings),+        CurrentDateFuncExprCommonSubexpr <$ Parsers.keyword "current_date",+        CurrentTimestampFuncExprCommonSubexpr <$> labeledIconst "current_timestamp",+        CurrentTimeFuncExprCommonSubexpr <$> labeledIconst "current_time",+        LocalTimestampFuncExprCommonSubexpr <$> labeledIconst "localtimestamp",+        LocalTimeFuncExprCommonSubexpr <$> labeledIconst "localtime",+        CurrentRoleFuncExprCommonSubexpr <$ Parsers.keyword "current_role",+        CurrentUserFuncExprCommonSubexpr <$ Parsers.keyword "current_user",+        SessionUserFuncExprCommonSubexpr <$ Parsers.keyword "session_user",+        UserFuncExprCommonSubexpr <$ Parsers.keyword "user",+        CurrentCatalogFuncExprCommonSubexpr <$ Parsers.keyword "current_catalog",+        CurrentSchemaFuncExprCommonSubexpr <$ Parsers.keyword "current_schema",+        Parsers.inParensWithClause (Parsers.keyword "cast") (CastFuncExprCommonSubexpr <$> parser settings <*> (Parsers.space1 *> Parsers.keyword "as" *> Parsers.space1 *> parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "extract") (ExtractFuncExprCommonSubexpr <$> optional (parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "overlay") (OverlayFuncExprCommonSubexpr <$> parser settings),+        Parsers.inParensWithClause (Parsers.keyword "position") (PositionFuncExprCommonSubexpr <$> optional (parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "substring") (SubstringFuncExprCommonSubexpr <$> optional (parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "treat") (TreatFuncExprCommonSubexpr <$> parser settings <*> (Parsers.space1 *> Parsers.keyword "as" *> Parsers.space1 *> parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "trim") (TrimFuncExprCommonSubexpr <$> optional (parser settings <* Parsers.space1) <*> parser settings),+        Parsers.inParensWithClause (Parsers.keyword "nullif") (NullIfFuncExprCommonSubexpr <$> parser settings <*> (Parsers.commaSeparator *> parser settings)),+        Parsers.inParensWithClause (Parsers.keyword "coalesce") (CoalesceFuncExprCommonSubexpr <$> parser settings),+        Parsers.inParensWithClause (Parsers.keyword "greatest") (GreatestFuncExprCommonSubexpr <$> parser settings),+        Parsers.inParensWithClause (Parsers.keyword "least") (LeastFuncExprCommonSubexpr <$> parser settings)+      ]+    where+      labeledIconst lbl = Parsers.keyword lbl *> Parser.endHead *> optional (Parsers.space *> Parsers.inParens Parsers.decimal)++instance Qc.Arbitrary FuncExprCommonSubexpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then+          Qc.oneof+            [ pure CurrentDateFuncExprCommonSubexpr,+              pure CurrentRoleFuncExprCommonSubexpr,+              pure CurrentUserFuncExprCommonSubexpr,+              pure SessionUserFuncExprCommonSubexpr,+              pure UserFuncExprCommonSubexpr,+              pure CurrentCatalogFuncExprCommonSubexpr,+              pure CurrentSchemaFuncExprCommonSubexpr+            ]+        else+          Qc.oneof+            [ CollationForFuncExprCommonSubexpr <$> Gens.downscale Qc.arbitrary,+              pure CurrentDateFuncExprCommonSubexpr,+              -- The @Iconst@ here is parsed via 'Parsers.decimal' (unsigned), so+              -- it must never be negative — mirroring+              -- 'PostgresqlSyntax.Ast.IntervalSecond'\'s own @nonNegative@.+              CurrentTimeFuncExprCommonSubexpr <$> nonNegativeMaybeInt64,+              CurrentTimestampFuncExprCommonSubexpr <$> nonNegativeMaybeInt64,+              LocalTimeFuncExprCommonSubexpr <$> nonNegativeMaybeInt64,+              LocalTimestampFuncExprCommonSubexpr <$> nonNegativeMaybeInt64,+              pure CurrentRoleFuncExprCommonSubexpr,+              pure CurrentUserFuncExprCommonSubexpr,+              pure SessionUserFuncExprCommonSubexpr,+              pure UserFuncExprCommonSubexpr,+              pure CurrentCatalogFuncExprCommonSubexpr,+              pure CurrentSchemaFuncExprCommonSubexpr,+              CastFuncExprCommonSubexpr <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+              ExtractFuncExprCommonSubexpr <$> Qc.arbitrary,+              OverlayFuncExprCommonSubexpr <$> Qc.arbitrary,+              PositionFuncExprCommonSubexpr <$> Qc.arbitrary,+              SubstringFuncExprCommonSubexpr <$> Qc.arbitrary,+              TreatFuncExprCommonSubexpr <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+              TrimFuncExprCommonSubexpr <$> Qc.arbitrary <*> Qc.arbitrary,+              NullIfFuncExprCommonSubexpr <$> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+              CoalesceFuncExprCommonSubexpr <$> Qc.arbitrary,+              GreatestFuncExprCommonSubexpr <$> Qc.arbitrary,+              LeastFuncExprCommonSubexpr <$> Qc.arbitrary+            ]+    where+      nonNegativeMaybeInt64 = Qc.oneof [pure Nothing, Just <$> nonNegativeInt64]+      nonNegativeInt64 = Qc.sized (\n -> Qc.choose (0, cap n))+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/FuncExprCommonSubexpr.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.FuncExprCommonSubexpr where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data FuncExprCommonSubexpr++instance Show FuncExprCommonSubexpr++instance Eq FuncExprCommonSubexpr++instance Ord FuncExprCommonSubexpr++instance Data FuncExprCommonSubexpr++instance IsAst FuncExprCommonSubexpr++instance Arbitrary FuncExprCommonSubexpr
+ library-internal/PostgresqlSyntax/Ast/FuncExprWindowless.hs view
@@ -0,0 +1,37 @@+module PostgresqlSyntax.Ast.FuncExprWindowless where++import PostgresqlSyntax.Ast.FuncApplication+import PostgresqlSyntax.Ast.FuncExprCommonSubexpr+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_expr_windowless:+--   | func_application+--   | func_expr_common_subexpr+-- @+data FuncExprWindowless+  = ApplicationFuncExprWindowless FuncApplication+  | CommonSubexprFuncExprWindowless FuncExprCommonSubexpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncExprWindowless where+  toTextBuilder settings = \case+    ApplicationFuncExprWindowless a -> toTextBuilder settings a+    CommonSubexprFuncExprWindowless a -> toTextBuilder settings a+  parser settings =+    asum+      [ CommonSubexprFuncExprWindowless <$> parser settings,+        ApplicationFuncExprWindowless <$> parser settings+      ]++instance Qc.Arbitrary FuncExprWindowless where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ApplicationFuncExprWindowless <$> Qc.arbitrary,+        CommonSubexprFuncExprWindowless <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/FuncName.hs view
@@ -0,0 +1,60 @@+module PostgresqlSyntax.Ast.FuncName where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Indirection+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- 'PostgresqlSyntax.Ast.ColId' and 'PostgresqlSyntax.Ast.TypeFunctionName'+-- are both bare aliases to 'Ident', but their /parsers/ (kept in+-- "PostgresqlSyntax.Parsing" since neither is extracted in this batch) are+-- more permissive than plain 'Ident'. Since this module sits below+-- "PostgresqlSyntax.Parsing" (no import cycle allowed), those flavored+-- element parsers are duplicated here, same as 'PostgresqlSyntax.Ast.NameList'.+--+-- ==== References+-- @+-- func_name:+--   | type_function_name+--   | ColId indirection+-- @+data FuncName+  = TypeFuncName Ident+  | IndirectedFuncName Ident Indirection+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncName where+  toTextBuilder settings = \case+    TypeFuncName a -> toTextBuilder settings a+    IndirectedFuncName a b -> toTextBuilder settings a <> toTextBuilder settings b+  parser settings =+    IndirectedFuncName+      <$> Parser.wrapToHead colIdLikeName+      <*> (Parsers.space *> parser settings)+        <|> TypeFuncName+      <$> typeFunctionNameLikeName+    where+      colIdLikeName =+        Parser.label "identifier" $+          parser settings+            <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)+      typeFunctionNameLikeName =+        Parsers.keywordNameFromSet UnquotedIdent KeywordSet.typeFunctionName+          <|> parser settings++instance Qc.Arbitrary FuncName where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then TypeFuncName <$> Qc.arbitrary+        else+          Qc.oneof+            [ TypeFuncName <$> Qc.arbitrary,+              IndirectedFuncName <$> Qc.arbitrary <*> Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/FuncTable.hs view
@@ -0,0 +1,50 @@+module PostgresqlSyntax.Ast.FuncTable where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FuncExprWindowless+import PostgresqlSyntax.Ast.OptOrdinality+import PostgresqlSyntax.Ast.RowsfromList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- func_table:+--   | func_expr_windowless opt_ordinality+--   | ROWS FROM '(' rowsfrom_list ')' opt_ordinality+-- @+data FuncTable+  = FuncExprFuncTable FuncExprWindowless OptOrdinality+  | RowsFromFuncTable RowsfromList OptOrdinality+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst FuncTable where+  toTextBuilder settings = \case+    FuncExprFuncTable a (OptOrdinality b) -> toTextBuilder settings a <> bool "" " WITH ORDINALITY" b+    RowsFromFuncTable a (OptOrdinality b) -> "ROWS FROM (" <> toTextBuilder settings a <> ")" <> bool "" " WITH ORDINALITY" b+  parser settings =+    asum+      [ do+          Parsers.keyword "rows"+          Parsers.space1+          Parsers.keyword "from"+          Parsers.space+          a <- Parsers.inParens (Parser.endHead *> parser settings)+          b <- OptOrdinality <$> Parsers.trueIfPresent (Parsers.space *> Parsers.keyword "with" *> Parsers.space1 *> Parsers.keyword "ordinality")+          return (RowsFromFuncTable a b),+        do+          a <- parser settings+          b <- OptOrdinality <$> Parsers.trueIfPresent (Parsers.space1 *> Parsers.keyword "with" *> Parsers.space1 *> Parsers.keyword "ordinality")+          return (FuncExprFuncTable a b)+      ]++instance Qc.Arbitrary FuncTable where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ FuncExprFuncTable <$> Qc.arbitrary <*> Qc.arbitrary,+        RowsFromFuncTable <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/GenericType.hs view
@@ -0,0 +1,45 @@+module PostgresqlSyntax.Ast.GenericType where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Attrs+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- GenericType:+--   | type_function_name opt_type_modifiers+--   | type_function_name attrs opt_type_modifiers+-- @+--+-- 'PostgresqlSyntax.Ast.TypeFunctionName' is a bare alias to 'Ident', but its+-- /parser/ (kept in "PostgresqlSyntax.Parsing" since @TypeFunctionName@+-- itself isn't extracted in this batch) is more permissive than plain+-- 'Ident'. Since this module sits below "PostgresqlSyntax.Parsing" (no+-- import cycle allowed), that TypeFunctionName-flavored element parser is+-- duplicated here (mirroring @typeFunctionName@'s definition), same as+-- 'PostgresqlSyntax.Ast.NameList'.+data GenericType = GenericType Ident (Maybe Attrs) (Maybe ExprList)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst GenericType where+  toTextBuilder settings (GenericType a b c) = toTextBuilder settings a <> foldMap (toTextBuilder settings) b <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . toTextBuilder settings) c+  parser settings = do+    a <- typeFunctionNameLikeName+    Parser.endHead+    b <- optional (Parsers.space *> parser settings)+    c <- optional (Parsers.space1 *> Parsers.inParens (parser settings))+    return (GenericType a b c)+    where+      typeFunctionNameLikeName = Parsers.keywordNameFromSet UnquotedIdent KeywordSet.typeFunctionName <|> parser settings++instance Qc.Arbitrary GenericType where+  shrink = Qc.genericShrink+  arbitrary = GenericType <$> arbitrary <*> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/GroupByItem.hs view
@@ -0,0 +1,68 @@+module PostgresqlSyntax.Ast.GroupByItem where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- group_by_item:+--   |  a_expr+--   |  empty_grouping_set+--   |  cube_clause+--   |  rollup_clause+--   |  grouping_sets_clause+-- empty_grouping_set:+--   |  '(' ')'+-- rollup_clause:+--   |  ROLLUP '(' expr_list ')'+-- cube_clause:+--   |  CUBE '(' expr_list ')'+-- grouping_sets_clause:+--   |  GROUPING SETS '(' group_by_list ')'+-- @+data GroupByItem+  = ExprGroupByItem AExpr+  | EmptyGroupingSetGroupByItem+  | RollupGroupByItem ExprList+  | CubeGroupByItem ExprList+  | GroupingSetsGroupByItem (NonEmpty GroupByItem)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst GroupByItem where+  toTextBuilder settings = \case+    ExprGroupByItem a -> toTextBuilder settings a+    EmptyGroupingSetGroupByItem -> "()"+    RollupGroupByItem a -> "ROLLUP (" <> toTextBuilder settings a <> ")"+    CubeGroupByItem a -> "CUBE (" <> toTextBuilder settings a <> ")"+    GroupingSetsGroupByItem a -> "GROUPING SETS (" <> TextBuilders.commaNonEmpty (toTextBuilder settings) a <> ")"+  parser settings =+    asum+      [ EmptyGroupingSetGroupByItem <$ (Parsers.char '(' *> Parsers.space *> Parsers.char ')'),+        RollupGroupByItem . ExprList <$> (Parsers.keyword "rollup" *> Parser.endHead *> Parsers.space *> Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (parser settings))),+        CubeGroupByItem . ExprList <$> (Parsers.keyword "cube" *> Parser.endHead *> Parsers.space *> Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (parser settings))),+        GroupingSetsGroupByItem <$> (Parsers.keyphrase "grouping sets" *> Parser.endHead *> Parsers.space *> Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (parser settings))),+        ExprGroupByItem <$> parser settings+      ]++instance Qc.Arbitrary GroupByItem where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then Qc.oneof [ExprGroupByItem <$> Gens.downscale Qc.arbitrary, pure EmptyGroupingSetGroupByItem]+        else+          Qc.oneof+            [ ExprGroupByItem <$> Gens.downscale Qc.arbitrary,+              pure EmptyGroupingSetGroupByItem,+              RollupGroupByItem <$> Qc.arbitrary,+              CubeGroupByItem <$> Qc.arbitrary,+              GroupingSetsGroupByItem <$> Gens.downscale (Gens.nonEmptyUpTo 2 Qc.arbitrary)+            ]
+ library-internal/PostgresqlSyntax/Ast/GroupClause.hs view
@@ -0,0 +1,35 @@+module PostgresqlSyntax.Ast.GroupClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.GroupByItem+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- group_clause:+--   |  GROUP_P BY set_quantifier group_by_list+--   |  /*EMPTY*/+-- @+--+-- @set_quantifier@ (@DISTINCT@\/@ALL@) is not modeled here — this+-- codebase's grammar subset doesn't support @GROUP BY DISTINCT@.+newtype GroupClause = GroupClause (NonEmpty GroupByItem)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst GroupClause where+  toTextBuilder settings (GroupClause a) = "GROUP BY " <> TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = do+    Parsers.keyphrase "group by"+    Parser.endHead+    Parsers.space1+    GroupClause <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary GroupClause where+  shrink = Qc.genericShrink+  arbitrary = GroupClause <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/HavingClause.hs view
@@ -0,0 +1,31 @@+module PostgresqlSyntax.Ast.HavingClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- having_clause:+--   |  HAVING a_expr+--   |  /*EMPTY*/+-- @+newtype HavingClause = HavingClause AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst HavingClause where+  toTextBuilder settings (HavingClause a) = "HAVING " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "having"+    Parser.endHead+    Parsers.space1+    HavingClause <$> parser settings++instance Qc.Arbitrary HavingClause where+  shrink = Qc.genericShrink+  arbitrary = HavingClause <$> Gens.downscale Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Iconst.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.Iconst where++import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- Iconst+-- @+newtype Iconst = Iconst Int64+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Iconst where+  toTextBuilder _settings (Iconst a) = TextBuilder.int64Dec a+  parser _settings = Iconst <$> Parsers.decimal++instance Qc.Arbitrary Iconst where+  shrink = Qc.genericShrink+  arbitrary = Iconst <$> Qc.sized (\n -> Qc.choose (0, cap n))+    where+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/Ident.hs view
@@ -0,0 +1,103 @@+module PostgresqlSyntax.Ast.Ident where++import qualified Data.Text as Text+import qualified HeadedMegaparsec as Parser+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.Shrinks as Shrinks+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude hiding (filter, try)+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc+import qualified TextBuilder++-- |+-- ==== References+-- @+-- IDENT+-- @+data Ident = QuotedIdent Text | UnquotedIdent Text+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Ident where+  toTextBuilder _settings = \case+    QuotedIdent a -> TextBuilder.char7 '"' <> TextBuilder.text (Text.replace "\"" "\"\"" a) <> TextBuilder.char7 '"'+    UnquotedIdent a -> TextBuilder.text a+  parser _settings = quotedName <|> Parsers.keywordNameByPredicate UnquotedIdent (not . Predicate.keyword)+    where+      quotedName = Parser.filter (const "Empty name") (not . Text.null) (Parsers.quotedString '"') & fmap QuotedIdent++-- |+-- ==== References+-- @+-- ColId:+--   |  IDENT+--   |  unreserved_keyword+--   |  col_name_keyword+-- @+--+-- Most grammar positions that hold an identifier (column\/table\/alias+-- names, ...) are actually @ColId@, not bare @IDENT@ — this is the+-- permissive variant that most 'Ident'-typed fields elsewhere in+-- "PostgresqlSyntax.Ast" should parse with, since 'Ident'\'s own generic+-- 'parser' only accepts the strict @IDENT@ token (no Parsers.keyword fallback).+colId :: Settings -> Parser Ident+colId settings =+  Parser.label "identifier" $+    parser settings+      <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)++-- |+-- ==== References+-- @+-- ColLabel:+--   |  IDENT+--   |  unreserved_keyword+--   |  col_name_keyword+--   |  type_func_name_keyword+--   |  reserved_keyword+-- @+colLabel :: Settings -> Parser Ident+colLabel settings =+  Parser.label "column label" $+    Parsers.keywordNameFromSet UnquotedIdent KeywordSet.keyword+      <|> parser settings++-- |+-- ==== References+-- @+-- type_function_name:+--   | IDENT+--   | unreserved_keyword+--   | type_func_name_keyword+-- @+typeFunctionName :: Settings -> Parser Ident+typeFunctionName settings =+  Parsers.keywordNameFromSet UnquotedIdent KeywordSet.typeFunctionName+    <|> parser settings++instance Qc.Arbitrary Ident where+  shrink = \case+    QuotedIdent a -> QuotedIdent <$> Shrinks.textTail a+    UnquotedIdent a -> UnquotedIdent <$> Shrinks.textTail a+  arbitrary =+    Qc.frequency+      [ (95, UnquotedIdent <$> unquotedIdentText),+        (5, QuotedIdent <$> quotedIdentText)+      ]+    where+      unquotedIdentText =+        ( do+            firstChar <- Qc.elements startChars+            restLength <- Qc.choose (0, 29)+            rest <- Qc.vectorOf restLength (Qc.elements contChars)+            pure (Text.pack (firstChar : rest))+        )+          `Qc.suchThat` (not . Predicate.keyword)+      startChars = ['a' .. 'z'] <> ['_']+      contChars = startChars <> ['0' .. '9'] <> ['$']+      quotedIdentText = do+        len <- Qc.choose (1, 30)+        Text.pack <$> Qc.vectorOf len (Qc.arbitrary `Qc.suchThat` (not . isControl))
+ library-internal/PostgresqlSyntax/Ast/ImplicitRow.hs view
@@ -0,0 +1,38 @@+module PostgresqlSyntax.Ast.ImplicitRow where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Extras.NonEmpty as NonEmpty+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- implicit_row:+--   | '(' expr_list ',' a_expr ')'+-- @+data ImplicitRow = ImplicitRow ExprList AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ImplicitRow where+  toTextBuilder settings (ImplicitRow a b) = TextBuilders.renderInParens (toTextBuilder settings a <> ", " <> toTextBuilder settings b)++  -- Parses the shared @a_expr@ once and then decides, from what follows,+  -- whether it's the sole element of the leading 'ExprList' or the trailing+  -- @a_expr@ — see 'PostgresqlSyntax.Extras.NonEmpty.consAndUnsnoc'.+  parser settings = Parsers.inParens $ do+    a <- Parser.wrapToHead (parser settings)+    Parsers.commaSeparator+    b <- Parsers.sep1 Parsers.commaSeparator (parser settings)+    return $ case NonEmpty.consAndUnsnoc a b of+      (c, d) -> ImplicitRow (ExprList c) d++instance Qc.Arbitrary ImplicitRow where+  shrink = Qc.genericShrink+  arbitrary = ImplicitRow <$> arbitrary <*> Gens.downscale arbitrary
+ library-internal/PostgresqlSyntax/Ast/InExpr.hs view
@@ -0,0 +1,70 @@+module PostgresqlSyntax.Ast.InExpr+  ( InExpr (..),+  )+where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (selectWithParensAExpr)+import PostgresqlSyntax.Ast.ExprList+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens, refineToSelectWithParens)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc+import qualified Text.Megaparsec as Megaparsec++-- |+-- ==== References+-- @+-- in_expr:+--   | select_with_parens+--   | '(' expr_list ')'+-- @+data InExpr+  = SelectInExpr SelectWithParens+  | ExprListInExpr ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InExpr where+  toTextBuilder settings = \case+    SelectInExpr a -> toTextBuilder settings a+    ExprListInExpr a -> TextBuilders.renderInParens (toTextBuilder settings a)+  parser settings =+    (ExprListInExpr <$> Parser.parse (Megaparsec.try (Parser.toParsec (Parsers.inParens (parser settings)))))+      <|> (SelectInExpr <$> Parser.wrapToHead (parser settings))++instance Qc.Arbitrary InExpr where+  shrink = fmap canonicalize . Qc.genericShrink+  arbitrary =+    canonicalize+      <$> Qc.sized+        ( \n ->+            if n <= 1+              then ExprListInExpr <$> Qc.arbitrary+              else+                Qc.oneof+                  [ SelectInExpr <$> Gens.downscale Qc.arbitrary,+                    ExprListInExpr <$> Qc.arbitrary+                  ]+        )++-- |+-- Collapses the non-canonical @SelectInExpr@-of-@WithParensSelectWithParens@+-- shape to the @ExprListInExpr@ shape the parser actually produces for it:+-- @in_expr@'s two productions, @select_with_parens@ and+-- @'(' expr_list ')'@, overlap whenever the parenthesised select itself+-- contains another parenthesised select, since a single-element+-- @expr_list@ can itself be that inner parenthesised select wrapped as a+-- @c_expr@. Both render to the same text; the parser's @expr_list@+-- alternative is tried first and so wins. Both 'arbitrary' and 'shrink'+-- can otherwise construct the non-canonical shape, which renders fine but+-- parses back to a different, canonical value and so breaks the+-- roundtrip property.+canonicalize :: InExpr -> InExpr+canonicalize = \case+  SelectInExpr a+    | Just inner <- refineToSelectWithParens a ->+        ExprListInExpr (ExprList (selectWithParensAExpr inner :| []))+  other -> other
+ library-internal/PostgresqlSyntax/Ast/IndexElem.hs view
@@ -0,0 +1,64 @@+module PostgresqlSyntax.Ast.IndexElem where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AnyName+import PostgresqlSyntax.Ast.AscDesc+import PostgresqlSyntax.Ast.IndexElemDef+import PostgresqlSyntax.Ast.NullsOrder+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- index_elem:+--   | ColId opt_collate opt_class opt_asc_desc opt_nulls_order+--   | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order+--   | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order+-- @+--+-- @opt_collate@\/@opt_class@ are bare aliases to+-- 'PostgresqlSyntax.Ast.AnyName'.+data IndexElem = IndexElem IndexElemDef (Maybe AnyName) (Maybe AnyName) (Maybe AscDesc) (Maybe NullsOrder)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IndexElem where+  toTextBuilder settings (IndexElem a b c d e) =+    toTextBuilder settings a+      <> TextBuilders.suffixMaybe collate b+      <> TextBuilders.suffixMaybe (toTextBuilder settings) c+      <> TextBuilders.suffixMaybe (toTextBuilder settings) d+      <> TextBuilders.suffixMaybe (toTextBuilder settings) e+    where+      collate = mappend "COLLATE " . toTextBuilder settings+  parser settings =+    IndexElem+      <$> (parser settings <* Parser.endHead)+      <*> optional (Parsers.space1 *> collate)+      <*> optional (Parsers.space1 *> class_)+      <*> optional (Parsers.space1 *> parser settings)+      <*> optional (Parsers.space1 *> parser settings)+    where+      collate = Parsers.keyword "collate" *> Parsers.space1 *> Parser.endHead *> parser settings++      -- gram.y:8558 index_elem: ColId index_elem_options, and gram.y:8596+      -- opt_nulls_order (index_elem_options inlines opt_qualified_name at+      -- gram.y:8525 for the operator-class name). That name is a bare+      -- ColId, so of the words that can terminate it only the unreserved+      -- NULLS (kwlist.h:315) is a genuine hazard — ASC/DESC are reserved+      -- (kwlist.h:47,138) and were never candidates.+      class_ = filteredParser settings ["nulls"]++instance Qc.Arbitrary IndexElem where+  shrink = Qc.genericShrink+  arbitrary =+    IndexElem+      <$> Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Qc.arbitrary+      <*> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/IndexElemDef.hs view
@@ -0,0 +1,46 @@+module PostgresqlSyntax.Ast.IndexElemDef where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.FuncExprWindowless+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+--   | ColId opt_collate opt_class opt_asc_desc opt_nulls_order+--   | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order+--   | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order+-- @+data IndexElemDef+  = IdIndexElemDef Ident+  | FuncIndexElemDef FuncExprWindowless+  | ExprIndexElemDef AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IndexElemDef where+  toTextBuilder settings = \case+    IdIndexElemDef a -> toTextBuilder settings a+    FuncIndexElemDef a -> toTextBuilder settings a+    ExprIndexElemDef a -> TextBuilders.renderInParens (toTextBuilder settings a)+  parser settings =+    ExprIndexElemDef+      <$> Parsers.inParens (parser settings)+        <|> FuncIndexElemDef+      <$> parser settings+        <|> IdIndexElemDef+      <$> colId settings++instance Qc.Arbitrary IndexElemDef where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ IdIndexElemDef <$> Qc.arbitrary,+        FuncIndexElemDef <$> Qc.arbitrary,+        ExprIndexElemDef <$> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/IndexParams.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.IndexParams where++import PostgresqlSyntax.Ast.IndexElem+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- index_params:+--   | index_elem+--   | index_params ',' index_elem+-- @+newtype IndexParams = IndexParams (NonEmpty IndexElem)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IndexParams where+  toTextBuilder settings (IndexParams a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = IndexParams <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary IndexParams where+  shrink = Qc.genericShrink+  arbitrary = IndexParams <$> Gens.nonEmptyUpTo 4 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Indirection.hs view
@@ -0,0 +1,26 @@+module PostgresqlSyntax.Ast.Indirection where++import Control.Applicative.Combinators.NonEmpty (some)+import PostgresqlSyntax.Ast.IndirectionEl+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (some)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- indirection:+--   |  indirection_el+--   |  indirection indirection_el+-- @+newtype Indirection = Indirection (NonEmpty IndirectionEl)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Indirection where+  toTextBuilder settings (Indirection a) = foldMap (toTextBuilder settings) a+  parser settings = Indirection <$> some (parser settings)++instance Qc.Arbitrary Indirection where+  shrink = Qc.genericShrink+  arbitrary = Indirection <$> Gens.nonEmptyUpTo 4 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/IndirectionEl.hs view
@@ -0,0 +1,104 @@+module PostgresqlSyntax.Ast.IndirectionEl where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- 'PostgresqlSyntax.Ast.AttrName' is a bare alias to 'PostgresqlSyntax.Ast.ColLabel',+-- which is a bare alias to 'Ident', but the @ColLabel@ /parser/ (kept in+-- "PostgresqlSyntax.Parsing" since @ColLabel@ itself isn't extracted in this+-- batch) is more permissive than plain 'Ident'. Since this module sits below+-- "PostgresqlSyntax.Parsing" (no import cycle allowed), that ColLabel-flavored+-- element parser is duplicated here, same as 'PostgresqlSyntax.Ast.NameList'.+--+-- ==== References+-- @+-- indirection_el:+--   |  '.' attr_name+--   |  '.' '*'+--   |  '[' a_expr ']'+--   |  '[' opt_slice_bound ':' opt_slice_bound ']'+-- opt_slice_bound:+--   |  a_expr+--   |  EMPTY+-- @+data IndirectionEl+  = AttrNameIndirectionEl Ident+  | AllIndirectionEl+  | ExprIndirectionEl AExpr+  | SliceIndirectionEl (Maybe AExpr) (Maybe AExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IndirectionEl where+  toTextBuilder settings = \case+    AttrNameIndirectionEl a -> "." <> toTextBuilder settings a+    AllIndirectionEl -> ".*"+    ExprIndirectionEl a -> TextBuilders.renderInBrackets (toTextBuilder settings a)+    SliceIndirectionEl a b -> TextBuilders.renderInBrackets (foldMap (toTextBuilder settings) a <> ":" <> foldMap (toTextBuilder settings) b)+  parser settings =+    asum+      [ do+          Parsers.char '.'+          Parser.endHead+          Parsers.space+          AllIndirectionEl <$ Parsers.char '*' <|> AttrNameIndirectionEl <$> colLabelLikeName,+        do+          Parsers.char '['+          Parser.endHead+          Parsers.space+          a <-+            asum+              [ do+                  Parsers.char ':'+                  Parser.endHead+                  Parsers.space+                  b <- optional (parser settings)+                  return (SliceIndirectionEl Nothing b),+                do+                  a <- parser settings+                  asum+                    [ do+                        Parsers.space+                        Parsers.char ':'+                        Parsers.space+                        b <- optional (parser settings)+                        return (SliceIndirectionEl (Just a) b),+                      return (ExprIndirectionEl a)+                    ]+              ]+          Parsers.space+          Parsers.char ']'+          return a+      ]+    where+      colLabelLikeName =+        Parser.label "column label" $+          Parsers.keywordNameFromSet UnquotedIdent KeywordSet.keyword+            <|> parser settings++instance Qc.Arbitrary IndirectionEl where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \size ->+      if size <= 1+        then+          Qc.oneof+            [ AttrNameIndirectionEl <$> Qc.arbitrary,+              pure AllIndirectionEl,+              pure (SliceIndirectionEl Nothing Nothing)+            ]+        else+          Qc.oneof+            [ AttrNameIndirectionEl <$> Qc.arbitrary,+              pure AllIndirectionEl,+              ExprIndirectionEl <$> Gens.downscale Qc.arbitrary,+              SliceIndirectionEl <$> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/InsertColumnItem.hs view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.InsertColumnItem where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Indirection+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- insert_column_item:+--   | ColId opt_indirection+-- @+data InsertColumnItem = InsertColumnItem Ident (Maybe Indirection)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InsertColumnItem where+  toTextBuilder settings (InsertColumnItem a b) = toTextBuilder settings a <> TextBuilders.suffixMaybe (toTextBuilder settings) b+  parser settings = do+    a <- colId settings+    Parser.endHead+    b <- optional (Parsers.space1 *> parser settings)+    return (InsertColumnItem a b)++instance Qc.Arbitrary InsertColumnItem where+  shrink = Qc.genericShrink+  arbitrary = InsertColumnItem <$> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/InsertColumnList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.InsertColumnList where++import PostgresqlSyntax.Ast.InsertColumnItem+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- insert_column_list:+--   | insert_column_item+--   | insert_column_list ',' insert_column_item+-- @+newtype InsertColumnList = InsertColumnList (NonEmpty InsertColumnItem)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InsertColumnList where+  toTextBuilder settings (InsertColumnList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = InsertColumnList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary InsertColumnList where+  shrink = Qc.genericShrink+  arbitrary = InsertColumnList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/InsertRest.hs view
@@ -0,0 +1,64 @@+module PostgresqlSyntax.Ast.InsertRest where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.InsertColumnList+import PostgresqlSyntax.Ast.OverrideKind+import PostgresqlSyntax.Ast.SelectStmt+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- insert_rest:+--   | SelectStmt+--   | OVERRIDING override_kind VALUE_P SelectStmt+--   | '(' insert_column_list ')' SelectStmt+--   | '(' insert_column_list ')' OVERRIDING override_kind VALUE_P SelectStmt+--   | DEFAULT VALUES+-- @+data InsertRest+  = SelectInsertRest (Maybe InsertColumnList) (Maybe OverrideKind) SelectStmt+  | DefaultValuesInsertRest+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InsertRest where+  toTextBuilder settings = \case+    SelectInsertRest a b c ->+      TextBuilders.optLexemes+        [ fmap (TextBuilders.renderInParens . toTextBuilder settings) a,+          fmap insertRestOverriding b,+          Just (toTextBuilder settings c)+        ]+    DefaultValuesInsertRest -> "DEFAULT VALUES"+    where+      insertRestOverriding a = "OVERRIDING " <> toTextBuilder settings a <> " VALUE"+  parser settings =+    asum+      [ DefaultValuesInsertRest <$ (Parsers.keyword "default" *> Parsers.space1 *> Parser.endHead *> Parsers.keyword "values"),+        do+          a <- optional (Parsers.inParens (parser settings) <* Parsers.space1)+          b <- optional $ do+            Parsers.keyword "overriding"+            Parsers.space1+            Parser.endHead+            b <- parser settings+            Parsers.space1+            Parsers.keyword "value"+            Parsers.space1+            return b+          c <- parser settings+          return (SelectInsertRest a b c)+      ]++instance Qc.Arbitrary InsertRest where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ SelectInsertRest <$> Gens.terminatingMaybe Qc.arbitrary <*> Qc.arbitrary <*> Qc.arbitrary,+        pure DefaultValuesInsertRest+      ]
+ library-internal/PostgresqlSyntax/Ast/InsertStmt.hs view
@@ -0,0 +1,57 @@+module PostgresqlSyntax.Ast.InsertStmt where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.InsertRest+import PostgresqlSyntax.Ast.InsertTarget+import PostgresqlSyntax.Ast.OnConflict+import PostgresqlSyntax.Ast.ReturningClause+import {-# SOURCE #-} PostgresqlSyntax.Ast.WithClause (WithClause)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- InsertStmt:+--   | opt_with_clause INSERT INTO insert_target insert_rest+--       opt_on_conflict returning_clause+-- @+data InsertStmt = InsertStmt (Maybe WithClause) InsertTarget InsertRest (Maybe OnConflict) (Maybe ReturningClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InsertStmt where+  toTextBuilder settings (InsertStmt a b c d e) =+    TextBuilders.prefixMaybe (toTextBuilder settings) a+      <> "INSERT INTO "+      <> toTextBuilder settings b+      <> " "+      <> toTextBuilder settings c+      <> TextBuilders.suffixMaybe (toTextBuilder settings) d+      <> TextBuilders.suffixMaybe (toTextBuilder settings) e+  parser settings = do+    a <- optional (Parser.wrapToHead (parser settings) <* Parsers.space1)+    Parsers.keyword "insert"+    Parsers.space1+    Parser.endHead+    Parsers.keyword "into"+    Parsers.space1+    b <- parser settings+    Parsers.space1+    c <- parser settings+    d <- optional (Parsers.space1 *> parser settings)+    e <- optional (Parsers.space1 *> parser settings)+    return (InsertStmt a b c d e)++instance Qc.Arbitrary InsertStmt where+  shrink = Qc.genericShrink+  arbitrary =+    InsertStmt+      <$> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)+      <*> Qc.arbitrary+      <*> Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/InsertTarget.hs view
@@ -0,0 +1,31 @@+module PostgresqlSyntax.Ast.InsertTarget where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.QualifiedName+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- insert_target:+--   | qualified_name+--   | qualified_name AS ColId+-- @+data InsertTarget = InsertTarget QualifiedName (Maybe Ident)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst InsertTarget where+  toTextBuilder settings (InsertTarget a b) = toTextBuilder settings a <> foldMap (mappend " AS " . toTextBuilder settings) b+  parser settings = do+    a <- parser settings+    Parser.endHead+    b <- optional (Parsers.space1 *> Parsers.keyword "as" *> Parsers.space1 *> Parser.endHead *> colId settings)+    return (InsertTarget a b)++instance Qc.Arbitrary InsertTarget where+  shrink = Qc.genericShrink+  arbitrary = InsertTarget <$> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/Interval.hs view
@@ -0,0 +1,94 @@+module PostgresqlSyntax.Ast.Interval where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.IntervalSecond+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_interval:+--   | YEAR_P+--   | MONTH_P+--   | DAY_P+--   | HOUR_P+--   | MINUTE_P+--   | interval_second+--   | YEAR_P TO MONTH_P+--   | DAY_P TO HOUR_P+--   | DAY_P TO MINUTE_P+--   | DAY_P TO interval_second+--   | HOUR_P TO MINUTE_P+--   | HOUR_P TO interval_second+--   | MINUTE_P TO interval_second+--   | EMPTY+-- @+data Interval+  = YearInterval+  | MonthInterval+  | DayInterval+  | HourInterval+  | MinuteInterval+  | SecondInterval IntervalSecond+  | YearToMonthInterval+  | DayToHourInterval+  | DayToMinuteInterval+  | DayToSecondInterval IntervalSecond+  | HourToMinuteInterval+  | HourToSecondInterval IntervalSecond+  | MinuteToSecondInterval IntervalSecond+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Interval where+  toTextBuilder settings = \case+    YearInterval -> "YEAR"+    MonthInterval -> "MONTH"+    DayInterval -> "DAY"+    HourInterval -> "HOUR"+    MinuteInterval -> "MINUTE"+    SecondInterval a -> toTextBuilder settings a+    YearToMonthInterval -> "YEAR TO MONTH"+    DayToHourInterval -> "DAY TO HOUR"+    DayToMinuteInterval -> "DAY TO MINUTE"+    DayToSecondInterval a -> "DAY TO " <> toTextBuilder settings a+    HourToMinuteInterval -> "HOUR TO MINUTE"+    HourToSecondInterval a -> "HOUR TO " <> toTextBuilder settings a+    MinuteToSecondInterval a -> "MINUTE TO " <> toTextBuilder settings a+  parser settings =+    asum+      [ YearToMonthInterval <$ Parsers.keyphrase "year to month",+        DayToHourInterval <$ Parsers.keyphrase "day to hour",+        DayToMinuteInterval <$ Parsers.keyphrase "day to minute",+        DayToSecondInterval <$> (Parsers.keyphrase "day to" *> Parsers.space1 *> Parser.endHead *> parser settings),+        HourToMinuteInterval <$ Parsers.keyphrase "hour to minute",+        HourToSecondInterval <$> (Parsers.keyphrase "hour to" *> Parsers.space1 *> Parser.endHead *> parser settings),+        MinuteToSecondInterval <$> (Parsers.keyphrase "minute to" *> Parsers.space1 *> Parser.endHead *> parser settings),+        YearInterval <$ Parsers.keyword "year",+        MonthInterval <$ Parsers.keyword "month",+        DayInterval <$ Parsers.keyword "day",+        HourInterval <$ Parsers.keyword "hour",+        MinuteInterval <$ Parsers.keyword "minute",+        SecondInterval <$> parser settings+      ]++instance Qc.Arbitrary Interval where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure YearInterval,+        pure MonthInterval,+        pure DayInterval,+        pure HourInterval,+        pure MinuteInterval,+        SecondInterval <$> Qc.arbitrary,+        pure YearToMonthInterval,+        pure DayToHourInterval,+        pure DayToMinuteInterval,+        DayToSecondInterval <$> Qc.arbitrary,+        pure HourToMinuteInterval,+        HourToSecondInterval <$> Qc.arbitrary,+        MinuteToSecondInterval <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/IntervalSecond.hs view
@@ -0,0 +1,36 @@+module PostgresqlSyntax.Ast.IntervalSecond where++import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- interval_second:+--   | SECOND_P+--   | SECOND_P '(' Iconst ')'+-- @+newtype IntervalSecond = IntervalSecond (Maybe Int64)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IntervalSecond where+  toTextBuilder _settings (IntervalSecond a) = case a of+    Nothing -> "SECOND"+    Just a' -> "SECOND " <> TextBuilders.renderInParens (TextBuilder.int64Dec a')+  parser _settings = do+    Parsers.keyword "second"+    a <- optional (Parsers.space *> Parsers.inParens Parsers.decimal)+    return (IntervalSecond a)++instance Qc.Arbitrary IntervalSecond where+  shrink = Qc.genericShrink+  arbitrary = IntervalSecond <$> Qc.oneof [pure Nothing, Just <$> nonNegative]+    where+      nonNegative = Qc.sized (\n -> Qc.choose (0, cap n))+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/IntoClause.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.IntoClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.OptTempTableName+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- into_clause:+--   |  INTO OptTempTableName+--   |  /*EMPTY*/+-- @+newtype IntoClause = IntoClause OptTempTableName+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst IntoClause where+  toTextBuilder settings (IntoClause a) = "INTO " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "into"+    Parser.endHead+    Parsers.space1+    IntoClause <$> parser settings++instance Qc.Arbitrary IntoClause where+  shrink = Qc.genericShrink+  arbitrary = IntoClause <$> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/JoinMeth.hs view
@@ -0,0 +1,64 @@+module PostgresqlSyntax.Ast.JoinMeth where++import PostgresqlSyntax.Ast.JoinQual+import PostgresqlSyntax.Ast.JoinType+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | table_ref CROSS JOIN table_ref+-- | table_ref join_type JOIN table_ref join_qual+-- | table_ref JOIN table_ref join_qual+-- | table_ref NATURAL join_type JOIN table_ref+-- | table_ref NATURAL JOIN table_ref+-- @+--+-- In the concrete grammar, a 'JoinQual' is only ever written /after/ the+-- second @table_ref@ — never contiguous with the rest of this type's own+-- text. 'PostgresqlSyntax.Ast.TableRef' (the recursion hub this lives+-- beside) therefore does its own hand-written interleaving of table refs+-- and join methods rather than calling this instance; this one exists so+-- 'JoinMeth' has a sensible, self-contained, round-trippable grammar in+-- isolation (e.g. for 'Arbitrary'), not because anything threads through+-- it.+data JoinMeth+  = CrossJoinMeth+  | QualJoinMeth (Maybe JoinType) JoinQual+  | NaturalJoinMeth (Maybe JoinType)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst JoinMeth where+  toTextBuilder settings = \case+    CrossJoinMeth -> "CROSS JOIN"+    QualJoinMeth a b -> TextBuilders.optLexemes [fmap (toTextBuilder settings) a, Just "JOIN", Just (toTextBuilder settings b)]+    NaturalJoinMeth a -> TextBuilders.optLexemes [Just "NATURAL", fmap (toTextBuilder settings) a, Just "JOIN"]+  parser settings =+    asum+      [ CrossJoinMeth <$ Parsers.keyphrase "cross join",+        do+          a <- optional (parser settings <* Parsers.space1)+          Parsers.keyword "join"+          Parsers.space1+          b <- parser settings+          return (QualJoinMeth a b),+        do+          Parsers.keyword "natural"+          Parsers.space1+          a <- optional (parser settings <* Parsers.space1)+          Parsers.keyword "join"+          return (NaturalJoinMeth a)+      ]++instance Qc.Arbitrary JoinMeth where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure CrossJoinMeth,+        QualJoinMeth <$> Qc.arbitrary <*> Qc.arbitrary,+        NaturalJoinMeth <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/JoinQual.hs view
@@ -0,0 +1,40 @@+module PostgresqlSyntax.Ast.JoinQual where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- join_qual:+--   |  USING '(' name_list ')'+--   |  ON a_expr+-- @+data JoinQual+  = UsingJoinQual (NonEmpty Ident)+  | OnJoinQual AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst JoinQual where+  toTextBuilder settings = \case+    UsingJoinQual a -> "USING (" <> TextBuilders.commaNonEmpty (toTextBuilder settings) a <> ")"+    OnJoinQual a -> "ON " <> toTextBuilder settings a+  parser settings =+    asum+      [ Parsers.keyword "using" *> Parsers.space1 *> Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (colId settings)) <&> UsingJoinQual,+        Parsers.keyword "on" *> Parsers.space1 *> parser settings <&> OnJoinQual+      ]++instance Qc.Arbitrary JoinQual where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ UsingJoinQual <$> Gens.nonEmptyUpTo 7 Qc.arbitrary,+        OnJoinQual <$> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/JoinType.hs view
@@ -0,0 +1,60 @@+module PostgresqlSyntax.Ast.JoinType where++import qualified HeadedMegaparsec as Parser+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | FULL join_outer+-- | LEFT join_outer+-- | RIGHT join_outer+-- | INNER_P+-- @+data JoinType+  = FullJoinType Bool+  | LeftJoinType Bool+  | RightJoinType Bool+  | InnerJoinType+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst JoinType where+  toTextBuilder _settings = \case+    FullJoinType a -> "FULL" <> if a then " OUTER" else ""+    LeftJoinType a -> "LEFT" <> if a then " OUTER" else ""+    RightJoinType a -> "RIGHT" <> if a then " OUTER" else ""+    InnerJoinType -> "INNER"+  parser _settings =+    asum+      [ do+          Parsers.keyword "full"+          Parser.endHead+          outer <- outerAfterSpace+          return (FullJoinType outer),+        do+          Parsers.keyword "left"+          Parser.endHead+          outer <- outerAfterSpace+          return (LeftJoinType outer),+        do+          Parsers.keyword "right"+          Parser.endHead+          outer <- outerAfterSpace+          return (RightJoinType outer),+        Parsers.keyword "inner" $> InnerJoinType+      ]+    where+      outerAfterSpace = (Parsers.space1 *> Parsers.keyword "outer") $> True <|> pure False++instance Qc.Arbitrary JoinType where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ FullJoinType <$> Qc.arbitrary,+        LeftJoinType <$> Qc.arbitrary,+        RightJoinType <$> Qc.arbitrary,+        pure InnerJoinType+      ]
+ library-internal/PostgresqlSyntax/Ast/JoinedTable.hs view
@@ -0,0 +1,58 @@+module PostgresqlSyntax.Ast.JoinedTable where++import PostgresqlSyntax.Ast.JoinMeth+import {-# SOURCE #-} PostgresqlSyntax.Ast.TableRef (TableRef, joinedTableParser, renderJoinedTable)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | '(' joined_table ')'+-- | table_ref CROSS JOIN table_ref+-- | table_ref join_type JOIN table_ref join_qual+-- | table_ref JOIN table_ref join_qual+-- | table_ref NATURAL join_type JOIN table_ref+-- | table_ref NATURAL JOIN table_ref+--+-- The options are covered by the `JoinMeth` type.+-- @+--+-- See 'PostgresqlSyntax.Ast.JoinMeth' for why this type's own 'IsAst'+-- instance isn't what 'PostgresqlSyntax.Ast.TableRef' actually uses to+-- parse\/render joined tables.+data JoinedTable+  = InParensJoinedTable JoinedTable+  | MethJoinedTable JoinMeth TableRef TableRef+  deriving (Show, Generic, Eq, Ord, Data)++-- |+-- Delegates to 'PostgresqlSyntax.Ast.TableRef.renderJoinedTable'\/+-- 'PostgresqlSyntax.Ast.TableRef.joinedTableParser' rather than combining+-- 'TableRef'\'s and 'JoinMeth'\'s own instances directly: a bare @table_ref@+-- parse is greedy — it absorbs any trailing @CROSS JOIN@\/@JOIN@\/@NATURAL+-- JOIN@ continuation into itself (see 'PostgresqlSyntax.Ast.TableRef'\'s+-- @recur@) — so parsing this type's own @b@ field with the plain exported+-- 'PostgresqlSyntax.Ast.TableRef.parser' would always swallow the @a@\/@c@+-- that's meant to follow it, and 'JoinMeth'\'s own renderer places a+-- 'PostgresqlSyntax.Ast.JoinQual' immediately after the @JOIN@ keyword+-- rather than after @c@ (see its own doc for why). 'TableRef' is the only+-- module with both this type and 'TableRef' in scope non-abstractly at+-- once, so it hosts the one correct, round-trippable implementation.+instance IsAst JoinedTable where+  toTextBuilder = renderJoinedTable+  parser = joinedTableParser++instance Qc.Arbitrary JoinedTable where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then MethJoinedTable <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary+        else+          Qc.oneof+            [ InParensJoinedTable <$> Gens.downscale Qc.arbitrary,+              MethJoinedTable <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/JoinedTable.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.JoinedTable where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data JoinedTable++instance Show JoinedTable++instance Eq JoinedTable++instance Ord JoinedTable++instance Data JoinedTable++instance IsAst JoinedTable++instance Arbitrary JoinedTable
+ library-internal/PostgresqlSyntax/Ast/LimitClause.hs view
@@ -0,0 +1,100 @@+module PostgresqlSyntax.Ast.LimitClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.SelectFetchFirstValue+import PostgresqlSyntax.Ast.SelectLimitValue+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- limit_clause:+--   | LIMIT select_limit_value+--   | LIMIT select_limit_value ',' select_offset_value+--   | FETCH first_or_next select_fetch_first_value row_or_rows ONLY+--   | FETCH first_or_next row_or_rows ONLY+-- select_offset_value:+--   | a_expr+-- first_or_next:+--   | FIRST_P+--   | NEXT+-- row_or_rows:+--   | ROW+--   | ROWS+-- @+data LimitClause+  = LimitLimitClause SelectLimitValue (Maybe AExpr)+  | FetchOnlyLimitClause Bool (Maybe SelectFetchFirstValue) Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst LimitClause where+  toTextBuilder settings = \case+    LimitLimitClause a b -> "LIMIT " <> toTextBuilder settings a <> foldMap (mappend ", " . toTextBuilder settings) b+    FetchOnlyLimitClause a b c ->+      TextBuilders.optLexemes+        [ Just "FETCH",+          Just (firstOrNext a),+          fmap (toTextBuilder settings) b,+          Just (rowOrRows c),+          Just "ONLY"+        ]+    where+      firstOrNext = bool "FIRST" "NEXT"+      rowOrRows = bool "ROW" "ROWS"+  parser settings =+    ( do+        Parsers.keyword "limit"+        Parser.endHead+        Parsers.space1+        a <- parser settings+        b <- optional $ do+          Parsers.commaSeparator+          parser settings+        return (LimitLimitClause a b)+    )+      <|> ( do+              Parsers.keyword "fetch"+              Parser.endHead+              Parsers.space1+              a <- firstOrNext+              Parsers.space1+              asum+                [ do+                    b <- rowOrRows+                    Parsers.space1+                    Parsers.keyword "only"+                    return (FetchOnlyLimitClause a Nothing b),+                  do+                    b <- parser settings+                    Parsers.space1+                    c <- rowOrRows+                    Parsers.space1+                    Parsers.keyword "only"+                    return (FetchOnlyLimitClause a (Just b) c)+                ]+          )+    where+      firstOrNext =+        False+          <$ Parsers.keyword "first"+            <|> True+          <$ Parsers.keyword "next"+      rowOrRows =+        True+          <$ Parsers.keyword "rows"+            <|> False+          <$ Parsers.keyword "row"++instance Qc.Arbitrary LimitClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ LimitLimitClause <$> Qc.arbitrary <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary),+        FetchOnlyLimitClause <$> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/MathOp.hs view
@@ -0,0 +1,76 @@+module PostgresqlSyntax.Ast.MathOp where++import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- MathOp:+--   | '+'+--   | '-'+--   | '*'+--   | '/'+--   | '%'+--   | '^'+--   | '<'+--   | '>'+--   | '='+--   | LESS_EQUALS+--   | GREATER_EQUALS+--   | NOT_EQUALS+-- @+data MathOp+  = PlusMathOp+  | MinusMathOp+  | AsteriskMathOp+  | SlashMathOp+  | PercentMathOp+  | ArrowUpMathOp+  | ArrowLeftMathOp+  | ArrowRightMathOp+  | EqualsMathOp+  | LessEqualsMathOp+  | GreaterEqualsMathOp+  | ArrowLeftArrowRightMathOp+  | ExclamationEqualsMathOp+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst MathOp where+  toTextBuilder _settings = \case+    PlusMathOp -> TextBuilder.char7 '+'+    MinusMathOp -> TextBuilder.char7 '-'+    AsteriskMathOp -> TextBuilder.char7 '*'+    SlashMathOp -> TextBuilder.char7 '/'+    PercentMathOp -> TextBuilder.char7 '%'+    ArrowUpMathOp -> TextBuilder.char7 '^'+    ArrowLeftMathOp -> TextBuilder.char7 '<'+    ArrowRightMathOp -> TextBuilder.char7 '>'+    EqualsMathOp -> TextBuilder.char7 '='+    LessEqualsMathOp -> "<="+    GreaterEqualsMathOp -> ">="+    ArrowLeftArrowRightMathOp -> "<>"+    ExclamationEqualsMathOp -> "!="+  parser _settings =+    asum+      [ ArrowLeftArrowRightMathOp <$ Parsers.string' "<>",+        GreaterEqualsMathOp <$ Parsers.string' ">=",+        ExclamationEqualsMathOp <$ Parsers.string' "!=",+        LessEqualsMathOp <$ Parsers.string' "<=",+        PlusMathOp <$ Parsers.char '+',+        MinusMathOp <$ Parsers.char '-',+        AsteriskMathOp <$ Parsers.char '*',+        SlashMathOp <$ Parsers.char '/',+        PercentMathOp <$ Parsers.char '%',+        ArrowUpMathOp <$ Parsers.char '^',+        ArrowLeftMathOp <$ Parsers.char '<',+        ArrowRightMathOp <$ Parsers.char '>',+        EqualsMathOp <$ Parsers.char '='+      ]++instance Qc.Arbitrary MathOp where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/NameList.hs view
@@ -0,0 +1,43 @@+module PostgresqlSyntax.Ast.NameList where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- name_list:+--   | name+--   | name_list ',' name+-- @+--+-- 'Name' is a bare alias to 'PostgresqlSyntax.Ast.ColId' which is a bare+-- alias to 'Ident', but the @ColId@ /parser/ (kept in "PostgresqlSyntax.Parsing"+-- since @ColId@ itself isn't extracted in this batch) is more permissive+-- than plain 'Ident': it additionally accepts the @unreserved_keyword@ and+-- @col_name_keyword@ lexical classes as identifiers. Since this module sits+-- below "PostgresqlSyntax.Parsing" (no import cycle allowed), that+-- ColId-flavored element parser is duplicated here (mirroring @colId@'s+-- definition) rather than reused, to preserve exact parsing behavior.+newtype NameList = NameList (NonEmpty Ident)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst NameList where+  toTextBuilder settings (NameList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = NameList <$> Parsers.sep1 Parsers.commaSeparator colIdLikeName+    where+      colIdLikeName =+        Parser.label "identifier" $+          parser settings+            <|> Parsers.keywordNameFromSet UnquotedIdent (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)++instance Qc.Arbitrary NameList where+  shrink = Qc.genericShrink+  arbitrary = NameList <$> Gens.nonEmptyUpTo 7 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/NullsOrder.hs view
@@ -0,0 +1,28 @@+module PostgresqlSyntax.Ast.NullsOrder where++import qualified HeadedMegaparsec as Parser+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_nulls_order:+--   | NULLS_LA FIRST_P+--   | NULLS_LA LAST_P+--   | EMPTY+-- @+data NullsOrder = FirstNullsOrder | LastNullsOrder+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst NullsOrder where+  toTextBuilder _settings = \case+    FirstNullsOrder -> "NULLS FIRST"+    LastNullsOrder -> "NULLS LAST"+  parser _settings = Parsers.keyword "nulls" *> Parsers.space1 *> Parser.endHead *> (FirstNullsOrder <$ Parsers.keyword "first" <|> LastNullsOrder <$ Parsers.keyword "last")++instance Qc.Arbitrary NullsOrder where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/Numeric.hs view
@@ -0,0 +1,99 @@+module PostgresqlSyntax.Ast.Numeric where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- Numeric:+--   | INT_P+--   | INTEGER+--   | SMALLINT+--   | BIGINT+--   | REAL+--   | FLOAT_P opt_float+--   | DOUBLE_P PRECISION+--   | DECIMAL_P opt_type_modifiers+--   | DEC opt_type_modifiers+--   | NUMERIC opt_type_modifiers+--   | BOOLEAN_P+-- opt_float:+--   | '(' Iconst ')'+--   | EMPTY+-- opt_type_modifiers:+--   | '(' expr_list ')'+--   | EMPTY+-- @+data Numeric+  = IntNumeric+  | IntegerNumeric+  | SmallintNumeric+  | BigintNumeric+  | RealNumeric+  | FloatNumeric (Maybe Int64)+  | DoublePrecisionNumeric+  | DecimalNumeric (Maybe ExprList)+  | DecNumeric (Maybe ExprList)+  | NumericNumeric (Maybe ExprList)+  | BooleanNumeric+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Numeric where+  toTextBuilder settings = \case+    IntNumeric -> "INT"+    IntegerNumeric -> "INTEGER"+    SmallintNumeric -> "SMALLINT"+    BigintNumeric -> "BIGINT"+    RealNumeric -> "REAL"+    FloatNumeric a -> "FLOAT" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . TextBuilder.int64Dec) a+    DoublePrecisionNumeric -> "DOUBLE PRECISION"+    DecimalNumeric a -> "DECIMAL" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . toTextBuilder settings) a+    DecNumeric a -> "DEC" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . toTextBuilder settings) a+    NumericNumeric a -> "NUMERIC" <> TextBuilders.suffixMaybe (TextBuilders.renderInParens . toTextBuilder settings) a+    BooleanNumeric -> "BOOLEAN"+  parser settings =+    asum+      [ IntegerNumeric <$ Parsers.keyword "integer",+        IntNumeric <$ Parsers.keyword "int",+        SmallintNumeric <$ Parsers.keyword "smallint",+        BigintNumeric <$ Parsers.keyword "bigint",+        RealNumeric <$ Parsers.keyword "real",+        FloatNumeric <$> (Parsers.keyword "float" *> Parser.endHead *> optional (Parsers.space *> Parsers.inParens Parsers.decimal)),+        DoublePrecisionNumeric <$ Parsers.keyphrase "double precision",+        DecimalNumeric <$> (Parsers.keyword "decimal" *> Parser.endHead *> optional (Parsers.space *> Parsers.inParens (parser settings))),+        DecNumeric <$> (Parsers.keyword "dec" *> Parser.endHead *> optional (Parsers.space *> Parsers.inParens (parser settings))),+        NumericNumeric <$> (Parsers.keyword "numeric" *> Parser.endHead *> optional (Parsers.space *> Parsers.inParens (parser settings))),+        BooleanNumeric <$ Parsers.keyword "boolean"+      ]++instance Qc.Arbitrary Numeric where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure IntNumeric,+        pure IntegerNumeric,+        pure SmallintNumeric,+        pure BigintNumeric,+        pure RealNumeric,+        -- The @Iconst@ here is parsed via 'Parsers.decimal' (unsigned), so,+        -- unlike a plain 'Int64', it must never be negative — mirroring+        -- 'PostgresqlSyntax.Ast.IntervalSecond'\'s own @nonNegative@.+        FloatNumeric <$> Qc.oneof [pure Nothing, Just <$> nonNegativeInt64],+        pure DoublePrecisionNumeric,+        DecimalNumeric <$> Qc.arbitrary,+        DecNumeric <$> Qc.arbitrary,+        NumericNumeric <$> Qc.arbitrary,+        pure BooleanNumeric+      ]+    where+      nonNegativeInt64 = Qc.sized (\n -> Qc.choose (0, cap n))+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/OffsetClause.hs view
@@ -0,0 +1,56 @@+module PostgresqlSyntax.Ast.OffsetClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.SelectFetchFirstValue+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- offset_clause:+--   | OFFSET select_offset_value+--   | OFFSET select_fetch_first_value row_or_rows+-- select_offset_value:+--   | a_expr+-- row_or_rows:+--   | ROW+--   | ROWS+-- @+data OffsetClause+  = ExprOffsetClause AExpr+  | FetchFirstOffsetClause SelectFetchFirstValue Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OffsetClause where+  toTextBuilder settings = \case+    ExprOffsetClause a -> "OFFSET " <> toTextBuilder settings a+    FetchFirstOffsetClause a b -> "OFFSET " <> toTextBuilder settings a <> " " <> rowOrRows b+    where+      rowOrRows = bool "ROW" "ROWS"+  parser settings = do+    Parsers.keyword "offset"+    Parser.endHead+    Parsers.space1+    asum+      [ FetchFirstOffsetClause <$> Parser.wrapToHead (parser settings) <*> (Parsers.space1 *> rowOrRows),+        ExprOffsetClause <$> parser settings+      ]+    where+      rowOrRows =+        True+          <$ Parsers.keyword "rows"+            <|> False+          <$ Parsers.keyword "row"++instance Qc.Arbitrary OffsetClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprOffsetClause <$> Gens.downscale Qc.arbitrary,+        FetchFirstOffsetClause <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/OnConflict.hs view
@@ -0,0 +1,40 @@+module PostgresqlSyntax.Ast.OnConflict where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ConfExpr+import PostgresqlSyntax.Ast.OnConflictDo+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_on_conflict:+--   | ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list where_clause+--   | ON CONFLICT opt_conf_expr DO NOTHING+--   | EMPTY+-- @+data OnConflict = OnConflict (Maybe ConfExpr) OnConflictDo+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OnConflict where+  toTextBuilder settings (OnConflict a b) = "ON CONFLICT" <> TextBuilders.suffixMaybe (toTextBuilder settings) a <> " DO " <> toTextBuilder settings b+  parser settings = do+    Parsers.keyword "on"+    Parsers.space1+    Parsers.keyword "conflict"+    Parsers.space1+    Parser.endHead+    a <- optional (parser settings <* Parsers.space1)+    Parsers.keyword "do"+    Parsers.space1+    b <- parser settings+    return (OnConflict a b)++instance Qc.Arbitrary OnConflict where+  shrink = Qc.genericShrink+  arbitrary = OnConflict <$> Gens.terminatingMaybe arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/OnConflictDo.hs view
@@ -0,0 +1,57 @@+module PostgresqlSyntax.Ast.OnConflictDo where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.SetClauseList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_on_conflict:+--   | ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list where_clause+--   | ON CONFLICT opt_conf_expr DO NOTHING+--   | EMPTY+-- @+--+-- @where_clause@ is inlined here as a bare 'PostgresqlSyntax.Ast.AExpr'+-- rather than going through 'PostgresqlSyntax.Ast.WhereClause'.+data OnConflictDo+  = UpdateOnConflictDo SetClauseList (Maybe AExpr)+  | NothingOnConflictDo+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OnConflictDo where+  toTextBuilder settings = \case+    UpdateOnConflictDo a b -> "UPDATE SET " <> toTextBuilder settings a <> TextBuilders.suffixMaybe whereClause b+    NothingOnConflictDo -> "NOTHING"+    where+      whereClause a = "WHERE " <> toTextBuilder settings a+  parser settings =+    asum+      [ NothingOnConflictDo <$ Parsers.keyword "nothing",+        do+          Parsers.keyword "update"+          Parsers.space1+          Parser.endHead+          Parsers.keyword "set"+          Parsers.space1+          a <- parser settings+          b <- optional (Parsers.space1 *> whereClause)+          return (UpdateOnConflictDo a b)+      ]+    where+      whereClause = Parsers.keyword "where" *> Parsers.space1 *> Parser.endHead *> parser settings++instance Qc.Arbitrary OnConflictDo where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ UpdateOnConflictDo <$> Qc.arbitrary <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary),+        pure NothingOnConflictDo+      ]
+ library-internal/PostgresqlSyntax/Ast/Op.hs view
@@ -0,0 +1,36 @@+module PostgresqlSyntax.Ast.Op where++import qualified Data.Text as Text+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.Shrinks as Shrinks+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude+import qualified PostgresqlSyntax.Validation as Validation+import qualified Test.QuickCheck as Qc+import qualified TextBuilder++-- |+-- ==== References+-- @+-- Op+-- @+newtype Op = Op Text+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Op where+  toTextBuilder _settings (Op a) = TextBuilder.text a+  parser _settings = do+    a <- Parsers.takeWhile1P Nothing Predicate.opChar+    case Validation.op a of+      Nothing -> return (Op a)+      Just err -> fail (Text.unpack err)++instance Qc.Arbitrary Op where+  shrink (Op a) = Op <$> filter (isNothing . Validation.op) (Shrinks.nonEmptyText a)+  arbitrary = Op <$> genOpText `Qc.suchThat` (isNothing . Validation.op)+    where+      genOpText = do+        len <- Qc.choose (1, 7)+        Text.pack <$> Qc.vectorOf len (Qc.elements opChars)+      opChars = "+-*/<>=~!@#%^&|`?"
+ library-internal/PostgresqlSyntax/Ast/OptOrdinality.hs view
@@ -0,0 +1,24 @@+module PostgresqlSyntax.Ast.OptOrdinality where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_ordinality:+--   | WITH_LA ORDINALITY+--   | EMPTY+-- @+newtype OptOrdinality = OptOrdinality Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OptOrdinality where+  toTextBuilder _settings (OptOrdinality a) = if a then "WITH ORDINALITY" else mempty+  parser _settings = OptOrdinality <$> Parsers.trueIfPresent (Parsers.keyword "with" *> Parsers.space1 *> Parsers.keyword "ordinality")++instance Qc.Arbitrary OptOrdinality where+  shrink = Qc.genericShrink+  arbitrary = OptOrdinality <$> arbitrary
+ library-internal/PostgresqlSyntax/Ast/OptTempTableName.hs view
@@ -0,0 +1,85 @@+module PostgresqlSyntax.Ast.OptTempTableName where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.QualifiedName+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- OptTempTableName:+--   |  TEMPORARY opt_table qualified_name+--   |  TEMP opt_table qualified_name+--   |  LOCAL TEMPORARY opt_table qualified_name+--   |  LOCAL TEMP opt_table qualified_name+--   |  GLOBAL TEMPORARY opt_table qualified_name+--   |  GLOBAL TEMP opt_table qualified_name+--   |  UNLOGGED opt_table qualified_name+--   |  TABLE qualified_name+--   |  qualified_name+-- @+data OptTempTableName+  = TemporaryOptTempTableName Bool QualifiedName+  | TempOptTempTableName Bool QualifiedName+  | LocalTemporaryOptTempTableName Bool QualifiedName+  | LocalTempOptTempTableName Bool QualifiedName+  | GlobalTemporaryOptTempTableName Bool QualifiedName+  | GlobalTempOptTempTableName Bool QualifiedName+  | UnloggedOptTempTableName Bool QualifiedName+  | TableOptTempTableName QualifiedName+  | QualifedOptTempTableName QualifiedName+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OptTempTableName where+  toTextBuilder settings = \case+    TemporaryOptTempTableName a b -> TextBuilders.optLexemes [Just "TEMPORARY", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    TempOptTempTableName a b -> TextBuilders.optLexemes [Just "TEMP", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    LocalTemporaryOptTempTableName a b -> TextBuilders.optLexemes [Just "LOCAL TEMPORARY", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    LocalTempOptTempTableName a b -> TextBuilders.optLexemes [Just "LOCAL TEMP", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    GlobalTemporaryOptTempTableName a b -> TextBuilders.optLexemes [Just "GLOBAL TEMPORARY", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    GlobalTempOptTempTableName a b -> TextBuilders.optLexemes [Just "GLOBAL TEMP", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    UnloggedOptTempTableName a b -> TextBuilders.optLexemes [Just "UNLOGGED", bool Nothing (Just "TABLE") a, Just (toTextBuilder settings b)]+    TableOptTempTableName a -> "TABLE " <> toTextBuilder settings a+    QualifedOptTempTableName a -> toTextBuilder settings a+  parser settings =+    asum+      [ do+          a <-+            asum+              [ TemporaryOptTempTableName <$ Parsers.keyword "temporary" <* Parsers.space1,+                TempOptTempTableName <$ Parsers.keyword "temp" <* Parsers.space1,+                LocalTemporaryOptTempTableName <$ Parsers.keyphrase "local temporary" <* Parsers.space1,+                LocalTempOptTempTableName <$ Parsers.keyphrase "local temp" <* Parsers.space1,+                GlobalTemporaryOptTempTableName <$ Parsers.keyphrase "global temporary" <* Parsers.space1,+                GlobalTempOptTempTableName <$ Parsers.keyphrase "global temp" <* Parsers.space1,+                UnloggedOptTempTableName <$ Parsers.keyword "unlogged" <* Parsers.space1+              ]+          b <- option False (True <$ Parsers.keyword "table" <* Parsers.space1)+          c <- parser settings+          return (a b c),+        do+          Parsers.keyword "table"+          Parsers.space1+          Parser.endHead+          TableOptTempTableName <$> parser settings,+        QualifedOptTempTableName <$> parser settings+      ]++instance Qc.Arbitrary OptTempTableName where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ TemporaryOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        TempOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        LocalTemporaryOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        LocalTempOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        GlobalTemporaryOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        GlobalTempOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        UnloggedOptTempTableName <$> Qc.arbitrary <*> Qc.arbitrary,+        TableOptTempTableName <$> Qc.arbitrary,+        QualifedOptTempTableName <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/OptVarying.hs view
@@ -0,0 +1,24 @@+module PostgresqlSyntax.Ast.OptVarying where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_varying:+--   | VARYING+--   | EMPTY+-- @+newtype OptVarying = OptVarying Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OptVarying where+  toTextBuilder _settings (OptVarying a) = if a then "VARYING" else mempty+  parser _settings = OptVarying <$> (True <$ Parsers.space1 <* Parsers.keyword "varying" <|> pure False)++instance Qc.Arbitrary OptVarying where+  shrink = Qc.genericShrink+  arbitrary = OptVarying <$> arbitrary
+ library-internal/PostgresqlSyntax/Ast/OverClause.hs view
@@ -0,0 +1,43 @@+module PostgresqlSyntax.Ast.OverClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.WindowSpecification+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- over_clause:+--   | OVER window_specification+--   | OVER ColId+--   | EMPTY+-- @+data OverClause+  = WindowOverClause WindowSpecification+  | ColIdOverClause Ident+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OverClause where+  toTextBuilder settings = \case+    WindowOverClause a -> "OVER " <> toTextBuilder settings a+    ColIdOverClause a -> "OVER " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "over"+    Parsers.space1+    Parser.endHead+    asum+      [ WindowOverClause <$> parser settings,+        ColIdOverClause <$> colId settings+      ]++instance Qc.Arbitrary OverClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ WindowOverClause <$> Qc.arbitrary,+        ColIdOverClause <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/OverlayList.hs view
@@ -0,0 +1,58 @@+module PostgresqlSyntax.Ast.OverlayList where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- overlay_list:+--   | a_expr overlay_placing substr_from substr_for+--   | a_expr overlay_placing substr_from+-- @+--+-- @overlay_placing@\/@substr_from@\/@substr_for@ are bare aliases to+-- 'PostgresqlSyntax.Ast.AExpr' (@PLACING a_expr@\/@FROM a_expr@\/@FOR+-- a_expr@ respectively); their tiny keyword-prefix wrapping is inlined here+-- rather than named, since 'PostgresqlSyntax.Ast.SubstrListFromFor' has its+-- own (differently-scoped) copy of the @FROM@\/@FOR@ half.+data OverlayList = OverlayList AExpr AExpr AExpr (Maybe AExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst OverlayList where+  toTextBuilder settings (OverlayList a b c d) =+    toTextBuilder settings a+      <> " PLACING "+      <> toTextBuilder settings b+      <> " FROM "+      <> toTextBuilder settings c+      <> TextBuilders.suffixMaybe (mappend "FOR " . toTextBuilder settings) d+  parser settings = do+    a <- parser settings+    Parsers.space1+    Parsers.keyword "placing"+    Parsers.space1+    Parser.endHead+    b <- parser settings+    Parsers.space1+    Parsers.keyword "from"+    Parsers.space1+    Parser.endHead+    c <- parser settings+    d <- optional (Parsers.space1 *> Parsers.keyword "for" *> Parsers.space1 *> Parser.endHead *> parser settings)+    return (OverlayList a b c d)++instance Qc.Arbitrary OverlayList where+  shrink = Qc.genericShrink+  arbitrary =+    OverlayList+      <$> Gens.downscale Qc.arbitrary+      <*> Gens.downscale Qc.arbitrary+      <*> Gens.downscale Qc.arbitrary+      <*> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)
+ library-internal/PostgresqlSyntax/Ast/OverrideKind.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.OverrideKind where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- override_kind:+--   | USER+--   | SYSTEM_P+-- @+data OverrideKind = UserOverrideKind | SystemOverrideKind+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst OverrideKind where+  toTextBuilder _settings = \case+    UserOverrideKind -> "USER"+    SystemOverrideKind -> "SYSTEM"+  parser _settings =+    asum+      [ UserOverrideKind <$ Parsers.keyword "user",+        SystemOverrideKind <$ Parsers.keyword "system"+      ]++instance Qc.Arbitrary OverrideKind where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/PositionList.hs view
@@ -0,0 +1,26 @@+module PostgresqlSyntax.Ast.PositionList where++import {-# SOURCE #-} PostgresqlSyntax.Ast.BExpr (BExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- position_list:+--   | b_expr IN_P b_expr+--   | EMPTY+-- @+data PositionList = PositionList BExpr BExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst PositionList where+  toTextBuilder settings (PositionList a b) = toTextBuilder settings a <> " IN " <> toTextBuilder settings b+  parser settings = PositionList <$> parser settings <*> (Parsers.space1 *> Parsers.keyword "in" *> Parsers.space1 *> parser settings)++instance Qc.Arbitrary PositionList where+  shrink = Qc.genericShrink+  arbitrary = PositionList <$> Gens.downscale arbitrary <*> Gens.downscale arbitrary
+ library-internal/PostgresqlSyntax/Ast/PreparableStmt.hs view
@@ -0,0 +1,55 @@+module PostgresqlSyntax.Ast.PreparableStmt where++import PostgresqlSyntax.Ast.CallStmt+import PostgresqlSyntax.Ast.DeleteStmt+import PostgresqlSyntax.Ast.InsertStmt+import PostgresqlSyntax.Ast.SelectStmt+import PostgresqlSyntax.Ast.UpdateStmt+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- PreparableStmt:+--   |  SelectStmt+--   |  InsertStmt+--   |  UpdateStmt+--   |  DeleteStmt+--   |  CallStmt+-- @+data PreparableStmt+  = SelectPreparableStmt SelectStmt+  | InsertPreparableStmt InsertStmt+  | UpdatePreparableStmt UpdateStmt+  | DeletePreparableStmt DeleteStmt+  | CallPreparableStmt CallStmt+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst PreparableStmt where+  toTextBuilder settings = \case+    SelectPreparableStmt a -> toTextBuilder settings a+    InsertPreparableStmt a -> toTextBuilder settings a+    UpdatePreparableStmt a -> toTextBuilder settings a+    DeletePreparableStmt a -> toTextBuilder settings a+    CallPreparableStmt a -> toTextBuilder settings a+  parser settings =+    asum+      [ SelectPreparableStmt <$> parser settings,+        InsertPreparableStmt <$> parser settings,+        UpdatePreparableStmt <$> parser settings,+        DeletePreparableStmt <$> parser settings,+        CallPreparableStmt <$> parser settings+      ]++instance Qc.Arbitrary PreparableStmt where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ SelectPreparableStmt <$> Qc.arbitrary,+        InsertPreparableStmt <$> Qc.arbitrary,+        UpdatePreparableStmt <$> Qc.arbitrary,+        DeletePreparableStmt <$> Qc.arbitrary,+        CallPreparableStmt <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/QualAllOp.hs view
@@ -0,0 +1,39 @@+module PostgresqlSyntax.Ast.QualAllOp where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AllOp+import PostgresqlSyntax.Ast.AnyOperator+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- qual_all_Op:+--   | all_Op+--   | OPERATOR '(' any_operator ')'+-- @+data QualAllOp+  = AllQualAllOp AllOp+  | AnyQualAllOp AnyOperator+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst QualAllOp where+  toTextBuilder settings = \case+    AllQualAllOp a -> toTextBuilder settings a+    AnyQualAllOp a -> "OPERATOR (" <> toTextBuilder settings a <> ")"+  parser settings =+    asum+      [ AnyQualAllOp <$> (Parsers.keyword "operator" *> Parsers.space *> Parsers.inParens (Parser.endHead *> parser settings)),+        AllQualAllOp <$> parser settings+      ]++instance Qc.Arbitrary QualAllOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ AllQualAllOp <$> Qc.arbitrary,+        AnyQualAllOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/QualOp.hs view
@@ -0,0 +1,38 @@+module PostgresqlSyntax.Ast.QualOp where++import PostgresqlSyntax.Ast.AnyOperator+import PostgresqlSyntax.Ast.Op+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- qual_Op:+--   | Op+--   | OPERATOR '(' any_operator ')'+-- @+data QualOp+  = OpQualOp Op+  | OperatorQualOp AnyOperator+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst QualOp where+  toTextBuilder settings = \case+    OpQualOp a -> toTextBuilder settings a+    OperatorQualOp a -> "OPERATOR (" <> toTextBuilder settings a <> ")"+  parser settings =+    asum+      [ OpQualOp <$> parser settings,+        OperatorQualOp <$> Parsers.inParensWithClause (Parsers.keyword "operator") (parser settings)+      ]++instance Qc.Arbitrary QualOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ OpQualOp <$> Qc.arbitrary,+        OperatorQualOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/QualifiedName.hs view
@@ -0,0 +1,43 @@+module PostgresqlSyntax.Ast.QualifiedName where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Indirection+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- columnref:+--   | ColId+--   | ColId indirection+-- qualified_name:+--   | ColId+--   | ColId indirection+-- @+data QualifiedName+  = SimpleQualifiedName Ident+  | IndirectedQualifiedName Ident Indirection+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst QualifiedName where+  toTextBuilder settings = \case+    SimpleQualifiedName a -> toTextBuilder settings a+    IndirectedQualifiedName a b -> toTextBuilder settings a <> toTextBuilder settings b+  parser settings =+    IndirectedQualifiedName+      <$> Parser.wrapToHead (colId settings)+      <*> (Parsers.space *> parser settings)+        <|> SimpleQualifiedName+      <$> colId settings++instance Qc.Arbitrary QualifiedName where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ SimpleQualifiedName <$> Qc.arbitrary,+        IndirectedQualifiedName <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/RelationExpr.hs view
@@ -0,0 +1,55 @@+module PostgresqlSyntax.Ast.RelationExpr where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.QualifiedName+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | qualified_name+-- | qualified_name '*'+-- | ONLY qualified_name+-- | ONLY '(' qualified_name ')'+-- @+data RelationExpr+  = -- | Name, then whether an asterisk is present.+    SimpleRelationExpr QualifiedName Bool+  | -- | Name, then whether parentheses are present.+    OnlyRelationExpr QualifiedName Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst RelationExpr where+  toTextBuilder settings = \case+    SimpleRelationExpr a b -> toTextBuilder settings a <> bool "" " *" b+    OnlyRelationExpr a b -> "ONLY " <> bool (toTextBuilder settings) (TextBuilders.renderInParens . toTextBuilder settings) b a+  parser settings =+    Parser.label "relation expression" $+      asum+        [ do+            Parsers.keyword "only"+            Parsers.space1+            name <- parser settings+            return (OnlyRelationExpr name False),+          Parsers.inParensWithClause (Parsers.keyword "only") (parser settings) <&> \a -> OnlyRelationExpr a True,+          do+            name <- parser settings+            asterisk <-+              asum+                [ True <$ (Parsers.space1 *> Parsers.char '*'),+                  pure False+                ]+            return (SimpleRelationExpr name asterisk)+        ]++instance Qc.Arbitrary RelationExpr where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ SimpleRelationExpr <$> Qc.arbitrary <*> Qc.arbitrary,+        OnlyRelationExpr <$> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/RelationExprOptAlias.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Ast.RelationExprOptAlias+  ( RelationExprOptAlias (..),+    customizedParser,+  )+where++import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.RelationExpr+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- relation_expr_opt_alias:+--   | relation_expr+--   | relation_expr ColId+--   | relation_expr AS ColId+-- @+data RelationExprOptAlias = RelationExprOptAlias RelationExpr (Maybe (Bool, Ident))+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst RelationExprOptAlias where+  toTextBuilder settings (RelationExprOptAlias a b) = toTextBuilder settings a <> TextBuilders.suffixMaybe optAlias b+    where+      optAlias (c, d) = bool "" "AS " c <> toTextBuilder settings d+  parser settings = customizedParser settings []++-- |+-- Parameterized over the alias identifier's excluded reserved words —+-- callers like @update_stmt@\/@delete_stmt@ need to keep e.g. @SET@\/+-- @USING@\/@WHERE@\/@RETURNING@ from being swallowed as a bare (unaliased)+-- alias. Mirrors the pre-extraction @relationExprOptAlias@ taking a+-- @reservedKeywords@ argument.+customizedParser :: Settings -> [Text] -> Parser RelationExprOptAlias+customizedParser settings reservedKeywords = do+  a <- parser settings+  b <- optional $ do+    Parsers.space1+    b <- Parsers.trueIfPresent (Parsers.keyword "as" *> Parsers.space1)+    c <- Parsers.filteredColIdLike UnquotedIdent (parser settings) reservedKeywords+    return (b, c)+  return (RelationExprOptAlias a b)++instance Qc.Arbitrary RelationExprOptAlias where+  shrink = Qc.genericShrink+  arbitrary = RelationExprOptAlias <$> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/ReturningClause.hs view
@@ -0,0 +1,33 @@+module PostgresqlSyntax.Ast.ReturningClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.TargetList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- returning_clause:+--   |  RETURNING returning_with_clause target_list+--   |  /*EMPTY*/+-- @+--+-- @returning_with_clause@ (the @WITH (...)@ modifier) is not modeled+-- here — not supported by this codebase's grammar subset.+newtype ReturningClause = ReturningClause TargetList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ReturningClause where+  toTextBuilder settings (ReturningClause a) = "RETURNING " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "returning"+    Parsers.space1+    Parser.endHead+    ReturningClause <$> parser settings++instance Qc.Arbitrary ReturningClause where+  shrink = Qc.genericShrink+  arbitrary = ReturningClause <$> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Row.hs view
@@ -0,0 +1,34 @@+module PostgresqlSyntax.Ast.Row where++import PostgresqlSyntax.Ast.ExplicitRow+import PostgresqlSyntax.Ast.ImplicitRow+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- row:+--   | ROW '(' expr_list ')'+--   | ROW '(' ')'+--   | '(' expr_list ',' a_expr ')'+-- @+data Row+  = ExplicitRowRow ExplicitRow+  | ImplicitRowRow ImplicitRow+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Row where+  toTextBuilder settings = \case+    ExplicitRowRow a -> toTextBuilder settings a+    ImplicitRowRow a -> toTextBuilder settings a+  parser settings = ExplicitRowRow <$> parser settings <|> ImplicitRowRow <$> parser settings++instance Qc.Arbitrary Row where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExplicitRowRow <$> Qc.arbitrary,+        ImplicitRowRow <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/RowsfromItem.hs view
@@ -0,0 +1,39 @@+module PostgresqlSyntax.Ast.RowsfromItem where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FuncExprWindowless+import PostgresqlSyntax.Ast.TableFuncElementList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- rowsfrom_item:+--   | func_expr_windowless opt_col_def_list+-- @+--+-- @opt_col_def_list@ is a bare alias to+-- 'PostgresqlSyntax.Ast.TableFuncElementList'.+data RowsfromItem = RowsfromItem FuncExprWindowless (Maybe TableFuncElementList)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst RowsfromItem where+  toTextBuilder settings (RowsfromItem a b) = toTextBuilder settings a <> TextBuilders.suffixMaybe colDefList b+    where+      colDefList a' = "AS (" <> toTextBuilder settings a' <> ")"+  parser settings = do+    a <- parser settings+    Parser.endHead+    b <- optional (Parsers.space1 *> colDefList)+    return (RowsfromItem a b)+    where+      colDefList = Parsers.keyword "as" *> Parsers.space *> Parsers.inParens (Parser.endHead *> parser settings)++instance Qc.Arbitrary RowsfromItem where+  shrink = Qc.genericShrink+  arbitrary = RowsfromItem <$> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/RowsfromList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.RowsfromList where++import PostgresqlSyntax.Ast.RowsfromItem+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- rowsfrom_list:+--   | rowsfrom_item+--   | rowsfrom_list ',' rowsfrom_item+-- @+newtype RowsfromList = RowsfromList (NonEmpty RowsfromItem)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst RowsfromList where+  toTextBuilder settings (RowsfromList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = RowsfromList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary RowsfromList where+  shrink = Qc.genericShrink+  arbitrary = RowsfromList <$> Gens.nonEmptyUpTo 7 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Sconst.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.Sconst where++import qualified Data.Text as Text+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.Shrinks as Shrinks+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc+import qualified TextBuilder++-- |+-- ==== References+-- @+-- Sconst+-- @+newtype Sconst = Sconst Text+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Sconst where+  toTextBuilder _settings (Sconst a) = "'" <> TextBuilder.text (Text.replace "'" "''" a) <> "'"+  parser _settings = Sconst <$> (Parsers.quotedString '\'' <|> Parsers.dollarQuotedSconst)++instance Qc.Arbitrary Sconst where+  shrink (Sconst a) = Sconst <$> Shrinks.text a+  arbitrary = do+    len <- Qc.sized (\n -> Qc.choose (0, min 1000 (n * 20)))+    Sconst . Text.pack <$> Qc.vectorOf len (Qc.arbitrary `Qc.suchThat` (not . isControl))
+ library-internal/PostgresqlSyntax/Ast/SelectBinOp.hs view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.SelectBinOp where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+--   |  select_clause UNION all_or_distinct select_clause+--   |  select_clause INTERSECT all_or_distinct select_clause+--   |  select_clause EXCEPT all_or_distinct select_clause+-- @+data SelectBinOp = UnionSelectBinOp | IntersectSelectBinOp | ExceptSelectBinOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectBinOp where+  toTextBuilder _settings = \case+    UnionSelectBinOp -> "UNION"+    IntersectSelectBinOp -> "INTERSECT"+    ExceptSelectBinOp -> "EXCEPT"+  parser _settings =+    asum+      [ Parsers.keyword "union" $> UnionSelectBinOp,+        Parsers.keyword "intersect" $> IntersectSelectBinOp,+        Parsers.keyword "except" $> ExceptSelectBinOp+      ]++instance Qc.Arbitrary SelectBinOp where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [UnionSelectBinOp, IntersectSelectBinOp, ExceptSelectBinOp]
+ library-internal/PostgresqlSyntax/Ast/SelectClause.hs view
@@ -0,0 +1,46 @@+module PostgresqlSyntax.Ast.SelectClause where++import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import {-# SOURCE #-} PostgresqlSyntax.Ast.SimpleSelect (SimpleSelect)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- select_clause:+--   |  simple_select+--   |  select_with_parens+-- @+--+-- This type's own 'IsAst' instance is a plain, non-recursive-suffix-aware+-- dispatch — the real @UNION@\/@INTERSECT@\/@EXCEPT@-chaining grammar+-- (where a @select_clause@ extends into a bigger+-- 'PostgresqlSyntax.Ast.SimpleSelect' via its @BinSimpleSelect@+-- constructor) is hosted in "PostgresqlSyntax.Ast.SimpleSelect" instead,+-- since only that module can construct @BinSimpleSelect@ values. See its+-- module documentation.+data SelectClause+  = SimpleSelectSelectClause SimpleSelect+  | WithParensSelectClause SelectWithParens+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectClause where+  toTextBuilder settings = \case+    SimpleSelectSelectClause a -> toTextBuilder settings a+    WithParensSelectClause a -> toTextBuilder settings a+  parser settings =+    SimpleSelectSelectClause+      <$> parser settings+        <|> WithParensSelectClause+      <$> parser settings++instance Qc.Arbitrary SelectClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.frequency+      [ (3, SimpleSelectSelectClause <$> Gens.downscale Qc.arbitrary),+        (1, WithParensSelectClause <$> Gens.downscale Qc.arbitrary)+      ]
+ library-internal/PostgresqlSyntax/Ast/SelectClause.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.SelectClause where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data SelectClause++instance Show SelectClause++instance Eq SelectClause++instance Ord SelectClause++instance Data SelectClause++instance IsAst SelectClause++instance Arbitrary SelectClause
+ library-internal/PostgresqlSyntax/Ast/SelectFetchFirstValue.hs view
@@ -0,0 +1,61 @@+module PostgresqlSyntax.Ast.SelectFetchFirstValue where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.CExpr+import PostgresqlSyntax.Ast.Fconst+import qualified PostgresqlSyntax.Extras.TextBuilder as TextBuilder+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- select_fetch_first_value:+--   | c_expr+--   | '+' I_or_F_const+--   | '-' I_or_F_const+-- @+data SelectFetchFirstValue+  = ExprSelectFetchFirstValue CExpr+  | NumSelectFetchFirstValue Bool (Either Int64 Double)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectFetchFirstValue where+  toTextBuilder settings = \case+    ExprSelectFetchFirstValue a -> toTextBuilder settings a+    NumSelectFetchFirstValue a b -> bool "+" "-" a <> intOrFloat b+    where+      intOrFloat = either TextBuilder.int64Dec TextBuilder.doubleDec+  parser settings =+    ExprSelectFetchFirstValue+      <$> parser settings+        <|> NumSelectFetchFirstValue+      <$> (plusOrMinus <* Parser.endHead <* Parsers.space)+      <*> iconstOrFconst+    where+      plusOrMinus = False <$ Parsers.char '+' <|> True <$ Parsers.char '-'+      iconstOrFconst = Right <$> (coerce <$> (parser settings :: Parser Fconst)) <|> Left <$> Parsers.decimal++instance Qc.Arbitrary SelectFetchFirstValue where+  shrink = Qc.genericShrink++  -- The magnitude is parsed via unsigned 'Parser.decimal'\/'Fconst' (the+  -- sign is this type's own separate @Bool@ field), so, like+  -- 'PostgresqlSyntax.Ast.IntervalSecond'\'s @nonNegative@, it must never be+  -- negative itself — otherwise e.g. @NumSelectFetchFirstValue True (Left+  -- (-1))@ renders as @-1@ with no space (a valid unsigned-magnitude+  -- rendering would be @- 1@ or just @-1@ for magnitude 1), doubling up+  -- into @--1@, which reparses as a line comment.+  arbitrary =+    Qc.oneof+      [ ExprSelectFetchFirstValue <$> Qc.arbitrary,+        NumSelectFetchFirstValue <$> Qc.arbitrary <*> Qc.oneof [Left <$> nonNegativeInt64, Right <$> nonNegativeDouble]+      ]+    where+      nonNegativeInt64 = Qc.sized (\n -> Qc.choose (0, cap n))+      nonNegativeDouble = abs <$> Qc.arbitrary+      cap n+        | n >= 62 = maxBound+        | otherwise = 2 ^ n
+ library-internal/PostgresqlSyntax/Ast/SelectLimit.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Ast.SelectLimit where++import PostgresqlSyntax.Ast.LimitClause+import PostgresqlSyntax.Ast.OffsetClause+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- select_limit:+--   | limit_clause offset_clause+--   | offset_clause limit_clause+--   | limit_clause+--   | offset_clause+-- @+data SelectLimit+  = LimitOffsetSelectLimit LimitClause OffsetClause+  | OffsetLimitSelectLimit OffsetClause LimitClause+  | LimitSelectLimit LimitClause+  | OffsetSelectLimit OffsetClause+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectLimit where+  toTextBuilder settings = \case+    LimitOffsetSelectLimit a b -> TextBuilders.lexemes [toTextBuilder settings a, toTextBuilder settings b]+    OffsetLimitSelectLimit a b -> TextBuilders.lexemes [toTextBuilder settings a, toTextBuilder settings b]+    LimitSelectLimit a -> toTextBuilder settings a+    OffsetSelectLimit a -> toTextBuilder settings a+  parser settings =+    asum+      [ do+          a <- parser settings+          LimitOffsetSelectLimit a <$> (Parsers.space1 *> parser settings) <|> pure (LimitSelectLimit a),+        do+          a <- parser settings+          OffsetLimitSelectLimit a <$> (Parsers.space1 *> parser settings) <|> pure (OffsetSelectLimit a)+      ]++instance Qc.Arbitrary SelectLimit where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ LimitOffsetSelectLimit <$> Qc.arbitrary <*> Qc.arbitrary,+        OffsetLimitSelectLimit <$> Qc.arbitrary <*> Qc.arbitrary,+        LimitSelectLimit <$> Qc.arbitrary,+        OffsetSelectLimit <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SelectLimitValue.hs view
@@ -0,0 +1,38 @@+module PostgresqlSyntax.Ast.SelectLimitValue where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- select_limit_value:+--   | a_expr+--   | ALL+-- @+data SelectLimitValue+  = ExprSelectLimitValue AExpr+  | AllSelectLimitValue+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectLimitValue where+  toTextBuilder settings = \case+    ExprSelectLimitValue a -> toTextBuilder settings a+    AllSelectLimitValue -> "ALL"+  parser settings =+    AllSelectLimitValue+      <$ Parsers.keyword "all"+        <|> ExprSelectLimitValue+      <$> parser settings++instance Qc.Arbitrary SelectLimitValue where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprSelectLimitValue <$> Gens.downscale Qc.arbitrary,+        pure AllSelectLimitValue+      ]
+ library-internal/PostgresqlSyntax/Ast/SelectNoParens.hs view
@@ -0,0 +1,133 @@+module PostgresqlSyntax.Ast.SelectNoParens+  ( SelectNoParens (..),+    unparenthesizedSelectNoParensParser,+    afterSelectWithParensClauseParser,+    refineToSelectWithParens,+  )+where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ForLockingClause+import PostgresqlSyntax.Ast.SelectClause+import PostgresqlSyntax.Ast.SelectLimit+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import {-# SOURCE #-} qualified PostgresqlSyntax.Ast.SimpleSelect as SimpleSelect+import PostgresqlSyntax.Ast.SortClause+import {-# SOURCE #-} PostgresqlSyntax.Ast.WithClause (WithClause)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- Covers the following cases:+--+-- @+-- select_no_parens:+--   |  simple_select+--   |  select_clause sort_clause+--   |  select_clause opt_sort_clause for_locking_clause opt_select_limit+--   |  select_clause opt_sort_clause select_limit opt_for_locking_clause+--   |  with_clause select_clause+--   |  with_clause select_clause sort_clause+--   |  with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit+--   |  with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause+-- @+data SelectNoParens+  = SelectNoParens (Maybe WithClause) SelectClause (Maybe SortClause) (Maybe SelectLimit) (Maybe ForLockingClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectNoParens where+  toTextBuilder settings (SelectNoParens a b c d e) =+    TextBuilders.optLexemes+      [ fmap (toTextBuilder settings) a,+        Just (toTextBuilder settings b),+        fmap (toTextBuilder settings) c,+        fmap (toTextBuilder settings) d,+        fmap (toTextBuilder settings) e+      ]+  parser settings = withSelectNoParens <|> simpleSelectNoParens+    where+      simpleSelectNoParens = sharedSelectNoParens settings Nothing+      withSelectNoParens = do+        with <- Parser.wrapToHead (parser settings)+        Parsers.space1+        sharedSelectNoParens settings (Just with)++sharedSelectNoParens :: Settings -> Maybe WithClause -> Parser SelectNoParens+sharedSelectNoParens settings with = SimpleSelect.selectClauseBase settings >>= selectNoParensAfterClauseParser settings with++-- |+-- 'PostgresqlSyntax.Ast.SelectNoParens.parser' restricted to the forms+-- that do not begin with @(@ — see the boot-exposed signature's doc.+unparenthesizedSelectNoParensParser :: Settings -> Parser SelectNoParens+unparenthesizedSelectNoParensParser settings =+  withSelectNoParens+    <|> (SimpleSelect.baseSimpleSelect settings >>= selectNoParensAfterClauseParser settings Nothing . SimpleSelectSelectClause)+  where+    withSelectNoParens = do+      with <- Parser.wrapToHead (parser settings)+      Parsers.space1+      sharedSelectNoParens settings (Just with)++selectNoParensAfterClauseParser :: Settings -> Maybe WithClause -> SelectClause -> Parser SelectNoParens+selectNoParensAfterClauseParser settings with clauseBase = do+  select <- SimpleSelect.extendSelectClause settings clauseBase+  sort <- optional (Parsers.space1 *> parser settings)+  (limit, forLocking) <- limitFirst <|> forLockingFirst <|> pure (Nothing, Nothing)+  return (SelectNoParens with select sort limit forLocking)+  where+    limitFirst = do+      limit <- Parsers.space1 *> parser settings+      forLocking <- optional (Parsers.space1 *> parser settings)+      pure (Just limit, forLocking)+    forLockingFirst = do+      forLocking <- Parsers.space1 *> parser settings+      limit <- optional (Parsers.space1 *> parser settings)+      pure (limit, Just forLocking)++-- |+-- Parses the remainder of a @select_no_parens@ whose leading clause is+-- already known to be a parenthesized select (@a@), then decides — per the+-- \"Canonical shape\" rule — whether the result collapses back down to just+-- that same parenthesized select (@Left@) or is a genuine+-- @SelectNoParens@ wrapping it (@Right@). Needed by+-- "PostgresqlSyntax.Ast.SelectWithParens", which can't pattern-match this+-- module's own 'SelectNoParens' constructor across the hub boundary.+afterSelectWithParensClauseParser :: Settings -> SelectWithParens -> Parser (Either SelectWithParens SelectNoParens)+afterSelectWithParensClauseParser settings a = do+  b <- selectNoParensAfterClauseParser settings Nothing (WithParensSelectClause a)+  return $ case refineToSelectWithParens b of+    Just c -> Left c+    Nothing -> Right b++-- |+-- If a 'SelectNoParens' is merely a trivial wrapper around a single+-- parenthesized select — no with-clause, sort, limit or locking clause of+-- its own — returns the wrapped 'SelectWithParens'. Used by+-- "PostgresqlSyntax.Ast.SelectWithParens" to canonicalize such wrappers+-- into its @WithParensSelectWithParens@ shape — see its \"Canonical+-- shape\" doc.+refineToSelectWithParens :: SelectNoParens -> Maybe SelectWithParens+refineToSelectWithParens = \case+  SelectNoParens Nothing (WithParensSelectClause c) Nothing Nothing Nothing -> Just c+  _ -> Nothing++instance Qc.Arbitrary SelectNoParens where+  shrink = Qc.genericShrink+  arbitrary =+    sized $ \size ->+      if size <= 1+        then do+          selectClause <- Qc.arbitrary+          return (SelectNoParens Nothing selectClause Nothing Nothing Nothing)+        else+          SelectNoParens+            <$> Gens.downscale Qc.arbitrary+            <*> Qc.arbitrary+            <*> Qc.arbitrary+            <*> Qc.arbitrary+            <*> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/SelectNoParens.hs-boot view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.SelectNoParens where++import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Either, Eq, Maybe, Ord, Parser, Show)+import PostgresqlSyntax.Settings (Settings)+import Test.QuickCheck (Arbitrary)++data SelectNoParens++instance Show SelectNoParens++instance Eq SelectNoParens++instance Ord SelectNoParens++instance Data SelectNoParens++instance IsAst SelectNoParens++instance Arbitrary SelectNoParens++unparenthesizedSelectNoParensParser :: Settings -> Parser SelectNoParens++afterSelectWithParensClauseParser :: Settings -> SelectWithParens -> Parser (Either SelectWithParens SelectNoParens)++refineToSelectWithParens :: SelectNoParens -> Maybe SelectWithParens
+ library-internal/PostgresqlSyntax/Ast/SelectStmt.hs view
@@ -0,0 +1,39 @@+module PostgresqlSyntax.Ast.SelectStmt where++import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectNoParens (SelectNoParens)+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- SelectStmt:+--   |  select_no_parens+--   |  select_with_parens+-- @+data SelectStmt+  = NoParensSelectStmt SelectNoParens+  | WithParensSelectStmt SelectWithParens+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectStmt where+  toTextBuilder settings = \case+    NoParensSelectStmt a -> toTextBuilder settings a+    WithParensSelectStmt a -> toTextBuilder settings a+  parser settings = NoParensSelectStmt <$> parser settings <|> WithParensSelectStmt <$> parser settings++instance Qc.Arbitrary SelectStmt where+  shrink = Qc.genericShrink++  -- @WithParensSelectStmt@ is unreachable via this type's own @parser@:+  -- @NoParensSelectStmt@'s alternative is tried first, and+  -- 'PostgresqlSyntax.Ast.SelectClause' (reachable from any+  -- @select_no_parens@ with every other clause absent) always accepts a+  -- parenthesized select too — so any @'(' select ')'@ text always parses+  -- as @NoParensSelectStmt (SelectNoParens Nothing (WithParensSelectClause+  -- _) Nothing Nothing Nothing)@, never as a bare @WithParensSelectStmt@.+  -- Generating the latter would therefore never round-trip.+  arbitrary = NoParensSelectStmt <$> Gens.downscale Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/SelectWithParens.hs view
@@ -0,0 +1,103 @@+module PostgresqlSyntax.Ast.SelectWithParens+  ( SelectWithParens (..),+    refineToSelectWithParens,+    withParensSelectWithParens,+  )+where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectNoParens (SelectNoParens)+import {-# SOURCE #-} qualified PostgresqlSyntax.Ast.SelectNoParens as SelectNoParens+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- select_with_parens:+--   |  '(' select_no_parens ')'+--   |  '(' select_with_parens ')'+-- @+data SelectWithParens+  = NoParensSelectWithParens SelectNoParens+  | WithParensSelectWithParens SelectWithParens+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SelectWithParens where+  toTextBuilder settings =+    TextBuilders.renderInParens . \case+      NoParensSelectWithParens a -> toTextBuilder settings a+      WithParensSelectWithParens a -> toTextBuilder settings a++  -- @gram.y@ gives two productions, @'(' select_with_parens ')'@ and+  -- @'(' select_no_parens ')'@, and they overlap: a @select_no_parens@ may+  -- itself be nothing but a @select_clause@, and a @select_clause@ may+  -- itself be a @select_with_parens@. Transcribed literally as two+  -- alternatives, that overlap makes every nested paren group get parsed+  -- twice — once down the @select_with_parens@ branch and once down the+  -- @select_no_parens@ branch — so the cost doubles with each level of+  -- nesting. So the shared prefix is parsed once and classified afterwards.+  --+  -- ==== Canonical shape+  --+  -- Because the productions overlap, @((select 1))@ has two+  -- representations: @WithParensSelectWithParens@ wrapping the inner+  -- parenthesised select, or @NoParensSelectWithParens@ of a+  -- @SelectNoParens@ whose clause is that same inner parenthesised select.+  -- Both render back to the same text. __The first is canonical.__+  parser settings = Parsers.inParens selectWithParensBody+    where+      selectWithParensBody =+        asum+          [ do+              a <- Parser.wrapToHead (parser settings)+              either WithParensSelectWithParens NoParensSelectWithParens <$> SelectNoParens.afterSelectWithParensClauseParser settings a,+            NoParensSelectWithParens <$> SelectNoParens.unparenthesizedSelectNoParensParser settings+          ]++instance Qc.Arbitrary SelectWithParens where+  shrink = fmap canonicalize . Qc.genericShrink+  arbitrary =+    canonicalize+      <$> Qc.frequency+        [ (3, NoParensSelectWithParens <$> Gens.downscale Qc.arbitrary),+          (1, WithParensSelectWithParens <$> Gens.downscale Qc.arbitrary)+        ]++-- |+-- Collapses the non-canonical @NoParensSelectWithParens@ shape described+-- above to the @WithParensSelectWithParens@ shape the parser actually+-- produces for it. Both 'arbitrary' and 'shrink' can otherwise construct+-- the non-canonical shape (shrinking the inner 'SelectNoParens' toward+-- @Nothing@s is exactly how it arises), which renders fine but parses back+-- to a different, canonical value and so breaks the roundtrip property.+canonicalize :: SelectWithParens -> SelectWithParens+canonicalize = \case+  NoParensSelectWithParens a+    | Just c <- SelectNoParens.refineToSelectWithParens a -> WithParensSelectWithParens c+  other -> other++-- |+-- If a 'SelectWithParens' is the @WithParensSelectWithParens@ wrapping of+-- another one, returns the wrapped value. Exposed for modules that can+-- only see 'SelectWithParens' via its @hs-boot@ (which keeps it abstract+-- to break an import cycle) — see "PostgresqlSyntax.Ast.InExpr", which+-- needs it to canonicalize a @select_with_parens@\/@expr_list@ ambiguity+-- analogous to the one described above.+refineToSelectWithParens :: SelectWithParens -> Maybe SelectWithParens+refineToSelectWithParens = \case+  WithParensSelectWithParens a -> Just a+  _ -> Nothing++-- |+-- Smart constructor for the @WithParensSelectWithParens@ shape, for modules+-- that can only see 'SelectWithParens' via its @hs-boot@ (which keeps it+-- abstract to break an import cycle) — see "PostgresqlSyntax.Ast.CExpr",+-- which needs it to canonicalize a @'(' a_expr ')'@\/@select_with_parens@+-- ambiguity analogous to the one described above.+withParensSelectWithParens :: SelectWithParens -> SelectWithParens+withParensSelectWithParens = WithParensSelectWithParens
+ library-internal/PostgresqlSyntax/Ast/SelectWithParens.hs-boot view
@@ -0,0 +1,25 @@+module PostgresqlSyntax.Ast.SelectWithParens where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Maybe, Ord, Show)+import Test.QuickCheck (Arbitrary)++data SelectWithParens++instance Show SelectWithParens++instance Eq SelectWithParens++instance Ord SelectWithParens++instance Data SelectWithParens++instance IsAst SelectWithParens++instance Arbitrary SelectWithParens++-- | See "PostgresqlSyntax.Ast.SelectWithParens" for the full documentation.+refineToSelectWithParens :: SelectWithParens -> Maybe SelectWithParens++-- | See "PostgresqlSyntax.Ast.SelectWithParens" for the full documentation.+withParensSelectWithParens :: SelectWithParens -> SelectWithParens
+ library-internal/PostgresqlSyntax/Ast/SetClause.hs view
@@ -0,0 +1,53 @@+module PostgresqlSyntax.Ast.SetClause where++import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.SetTarget+import PostgresqlSyntax.Ast.SetTargetList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- set_clause:+--   | set_target '=' a_expr+--   | '(' set_target_list ')' '=' a_expr+-- @+data SetClause+  = TargetSetClause SetTarget AExpr+  | TargetListSetClause SetTargetList AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SetClause where+  toTextBuilder settings = \case+    TargetSetClause a b -> toTextBuilder settings a <> " = " <> toTextBuilder settings b+    TargetListSetClause a b -> TextBuilders.renderInParens (toTextBuilder settings a) <> " = " <> toTextBuilder settings b+  parser settings =+    asum+      [ do+          a <- Parsers.inParens (parser settings)+          Parsers.space+          Parsers.char '='+          Parsers.space+          b <- parser settings+          return (TargetListSetClause a b),+        do+          a <- parser settings+          Parsers.space+          Parsers.char '='+          Parsers.space+          b <- parser settings+          return (TargetSetClause a b)+      ]++instance Qc.Arbitrary SetClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ TargetSetClause <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+        TargetListSetClause <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SetClauseList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.SetClauseList where++import PostgresqlSyntax.Ast.SetClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- set_clause_list:+--   | set_clause+--   | set_clause_list ',' set_clause+-- @+newtype SetClauseList = SetClauseList (NonEmpty SetClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SetClauseList where+  toTextBuilder settings (SetClauseList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = SetClauseList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary SetClauseList where+  shrink = Qc.genericShrink+  arbitrary = SetClauseList <$> Gens.nonEmptyUpTo 9 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/SetTarget.hs view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.SetTarget where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Indirection+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- set_target:+--   | ColId opt_indirection+-- @+data SetTarget = SetTarget Ident (Maybe Indirection)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SetTarget where+  toTextBuilder settings (SetTarget a b) = toTextBuilder settings a <> TextBuilders.suffixMaybe (toTextBuilder settings) b+  parser settings = do+    a <- colId settings+    Parser.endHead+    b <- optional (Parsers.space1 *> parser settings)+    return (SetTarget a b)++instance Qc.Arbitrary SetTarget where+  shrink = Qc.genericShrink+  arbitrary = SetTarget <$> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/SetTargetList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.SetTargetList where++import PostgresqlSyntax.Ast.SetTarget+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- set_target_list:+--   | set_target+--   | set_target_list ',' set_target+-- @+newtype SetTargetList = SetTargetList (NonEmpty SetTarget)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SetTargetList where+  toTextBuilder settings (SetTargetList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = SetTargetList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary SetTargetList where+  shrink = Qc.genericShrink+  arbitrary = SetTargetList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/SimpleSelect.hs view
@@ -0,0 +1,184 @@+module PostgresqlSyntax.Ast.SimpleSelect+  ( SimpleSelect (..),+    baseSimpleSelect,+    selectClauseBase,+    extendSelectClause,+  )+where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FromClause+import PostgresqlSyntax.Ast.GroupClause+import PostgresqlSyntax.Ast.HavingClause+import PostgresqlSyntax.Ast.IntoClause+import PostgresqlSyntax.Ast.RelationExpr+import PostgresqlSyntax.Ast.SelectBinOp+import PostgresqlSyntax.Ast.SelectClause+import PostgresqlSyntax.Ast.Targeting+import PostgresqlSyntax.Ast.ValuesClause+import PostgresqlSyntax.Ast.WhereClause+import PostgresqlSyntax.Ast.WindowClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc+import qualified Text.Megaparsec as Megaparsec++-- |+-- ==== References+-- @+-- simple_select:+--   |  SELECT opt_all_clause opt_target_list+--       into_clause from_clause where_clause+--       group_clause having_clause window_clause+--   |  SELECT distinct_clause target_list+--       into_clause from_clause where_clause+--       group_clause having_clause window_clause+--   |  values_clause+--   |  TABLE relation_expr+--   |  select_clause UNION all_or_distinct select_clause+--   |  select_clause INTERSECT all_or_distinct select_clause+--   |  select_clause EXCEPT all_or_distinct select_clause+-- @+--+-- Hosts the real @select_clause@ grammar (including its+-- @UNION@\/@INTERSECT@\/@EXCEPT@-chaining) for both itself and+-- "PostgresqlSyntax.Ast.SelectNoParens", which shares it — see+-- 'PostgresqlSyntax.Ast.SelectClause'\'s module documentation for why.+data SimpleSelect+  = NormalSimpleSelect (Maybe Targeting) (Maybe IntoClause) (Maybe FromClause) (Maybe WhereClause) (Maybe GroupClause) (Maybe HavingClause) (Maybe WindowClause)+  | ValuesSimpleSelect ValuesClause+  | TableSimpleSelect RelationExpr+  | BinSimpleSelect SelectBinOp SelectClause (Maybe Bool) SelectClause+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SimpleSelect where+  toTextBuilder settings = \case+    NormalSimpleSelect a b c d e f g ->+      TextBuilders.optLexemes+        [ Just "SELECT",+          fmap (toTextBuilder settings) a,+          fmap (toTextBuilder settings) b,+          fmap (toTextBuilder settings) c,+          fmap (toTextBuilder settings) d,+          fmap (toTextBuilder settings) e,+          fmap (toTextBuilder settings) f,+          fmap (toTextBuilder settings) g+        ]+    ValuesSimpleSelect a -> toTextBuilder settings a+    TableSimpleSelect a -> "TABLE " <> toTextBuilder settings a+    BinSimpleSelect a b c d -> toTextBuilder settings b <> " " <> toTextBuilder settings a <> foldMap (mappend " " . TextBuilders.renderAllOrDistinct) c <> " " <> toTextBuilder settings d+  parser settings = do+    a <- baseSimpleSelect settings <|> Parser.parse (Megaparsec.try (Parser.toParsec withParensHead))+    extendMany suffix a+    where+      suffix headSimpleSelect = binopExtension (SimpleSelectSelectClause headSimpleSelect)+      withParensHead = do+        swp <- parser settings+        binopExtension (WithParensSelectClause swp)+      binopExtension headClause = do+        op <- Parsers.space1 *> parser settings <* Parsers.space1+        Parser.endHead+        distinct <- optional (Parsers.allOrDistinct <* Parsers.space1)+        rhs <- selectClauseBase settings >>= extendSelectClause settings+        return (BinSimpleSelect op headClause distinct rhs)++-- |+-- The non-recursive base cases only (no @select_clause BINOP+-- select_clause@ extension) — see this module's own boot-exposed+-- signature.+baseSimpleSelect :: Settings -> Parser SimpleSelect+baseSimpleSelect settings =+  asum+    [ do+        Parsers.keyword "select"+        Parsers.notFollowedBy $ Parsers.satisfy isAlphaNum+        Parser.endHead+        targeting <- optional (Parsers.space1 *> parser settings)+        intoClause <- optional (Parsers.space1 *> parser settings)+        fromClause <- optional (Parsers.space1 *> parser settings)+        whereClause <- optional (Parsers.space1 *> parser settings)+        groupClause <- optional (Parsers.space1 *> parser settings)+        havingClause <- optional (Parsers.space1 *> parser settings)+        windowClause <- optional (Parsers.space1 *> parser settings)+        return (NormalSimpleSelect targeting intoClause fromClause whereClause groupClause havingClause windowClause),+      do+        Parsers.keyword "table"+        Parsers.space1+        Parser.endHead+        TableSimpleSelect <$> parser settings,+      ValuesSimpleSelect <$> parser settings+    ]++selectClauseBase :: Settings -> Parser SelectClause+selectClauseBase settings =+  asum+    [ WithParensSelectClause <$> parser settings,+      SimpleSelectSelectClause <$> baseSimpleSelect settings+    ]++extendSelectClause :: Settings -> SelectClause -> Parser SelectClause+extendSelectClause settings = extendMany suffix+  where+    suffix headSelectClause = SimpleSelectSelectClause <$> extensionSimpleSelect headSelectClause+    extensionSimpleSelect headSelectClause = do+      op <- Parsers.space1 *> parser settings <* Parsers.space1+      Parser.endHead+      distinct <- optional (Parsers.allOrDistinct <* Parsers.space1)+      rhs <- selectClauseBase settings >>= extendSelectClause settings+      return (BinSimpleSelect op headSelectClause distinct rhs)++instance Qc.Arbitrary SimpleSelect where+  shrink = fmap canonicalize . Qc.genericShrink+  arbitrary =+    canonicalize+      <$> Qc.sized+        ( \n ->+            if n <= 1+              then TableSimpleSelect <$> Qc.arbitrary+              else+                Qc.oneof+                  [ NormalSimpleSelect+                      <$> Qc.arbitrary+                      <*> Qc.arbitrary+                      <*> Qc.arbitrary+                      <*> Gens.terminatingMaybe Qc.arbitrary+                      <*> Qc.arbitrary+                      <*> Gens.terminatingMaybe Qc.arbitrary+                      <*> Qc.arbitrary,+                    ValuesSimpleSelect <$> Qc.arbitrary,+                    TableSimpleSelect <$> Qc.arbitrary,+                    BinSimpleSelect <$> Qc.arbitrary <*> Qc.arbitrary <*> Qc.arbitrary <*> Qc.arbitrary+                  ]+        )++-- |+-- Collapses a left-associated @BinSimpleSelect@ chain (@(a OP1 b) OP2+-- c@) to the right-associated shape (@a OP1 (b OP2 c)@) that the parser+-- actually produces: 'parser' above parses each operator's right-hand+-- side via 'extendSelectClause', which itself greedily consumes the rest+-- of the chain before returning — so a chain of @N@ operators nests+-- entirely to the right, and only that shape is reachable by parsing the+-- rendered text (both shapes render identically, since rendering doesn't+-- parenthesize chain elements). Both 'arbitrary' and 'shrink' can+-- otherwise construct the non-canonical shape, which renders fine but+-- parses back to a different, canonical value and so breaks the+-- roundtrip property.+canonicalize :: SimpleSelect -> SimpleSelect+canonicalize s@(BinSimpleSelect {}) =+  case rest of+    (op, distinct, next) : more -> BinSimpleSelect op headClause distinct (buildRight next more)+    [] -> s+  where+    (headClause, rest) = flattenChain (SimpleSelectSelectClause s)+    buildRight lastClause [] = lastClause+    buildRight clause ((op, distinct, next) : more) = SimpleSelectSelectClause (BinSimpleSelect op clause distinct (buildRight next more))+    flattenChain (SimpleSelectSelectClause (BinSimpleSelect op lhs distinct rhs)) =+      let (lhsHead, lhsRest) = flattenChain lhs+          (rhsHead, rhsRest) = flattenChain rhs+       in (lhsHead, lhsRest <> [(op, distinct, rhsHead)] <> rhsRest)+    flattenChain c = (c, [])+canonicalize other = other
+ library-internal/PostgresqlSyntax/Ast/SimpleSelect.hs-boot view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.SimpleSelect where++import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectClause (SelectClause)+import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Parser, Show)+import PostgresqlSyntax.Settings (Settings)+import Test.QuickCheck (Arbitrary)++data SimpleSelect++instance Show SimpleSelect++instance Eq SimpleSelect++instance Ord SimpleSelect++instance Data SimpleSelect++instance IsAst SimpleSelect++instance Arbitrary SimpleSelect++baseSimpleSelect :: Settings -> Parser SimpleSelect++selectClauseBase :: Settings -> Parser SelectClause++extendSelectClause :: Settings -> SelectClause -> Parser SelectClause
+ library-internal/PostgresqlSyntax/Ast/SimpleTypename.hs view
@@ -0,0 +1,74 @@+module PostgresqlSyntax.Ast.SimpleTypename where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Bit+import PostgresqlSyntax.Ast.Character+import PostgresqlSyntax.Ast.ConstDatetime+import PostgresqlSyntax.Ast.GenericType+import PostgresqlSyntax.Ast.Iconst+import PostgresqlSyntax.Ast.Interval+import PostgresqlSyntax.Ast.Numeric+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- SimpleTypename:+--   | GenericType+--   | Numeric+--   | Bit+--   | Character+--   | ConstDatetime+--   | ConstInterval opt_interval+--   | ConstInterval '(' Iconst ')'+-- ConstInterval:+--   | INTERVAL+-- @+data SimpleTypename+  = GenericTypeSimpleTypename GenericType+  | NumericSimpleTypename Numeric+  | BitSimpleTypename Bit+  | CharacterSimpleTypename Character+  | ConstDatetimeSimpleTypename ConstDatetime+  | ConstIntervalSimpleTypename (Either (Maybe Interval) Iconst)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SimpleTypename where+  toTextBuilder settings = \case+    GenericTypeSimpleTypename a -> toTextBuilder settings a+    NumericSimpleTypename a -> toTextBuilder settings a+    BitSimpleTypename a -> toTextBuilder settings a+    CharacterSimpleTypename a -> toTextBuilder settings a+    ConstDatetimeSimpleTypename a -> toTextBuilder settings a+    ConstIntervalSimpleTypename a -> "INTERVAL" <> either (TextBuilders.suffixMaybe (toTextBuilder settings)) (mappend " " . TextBuilders.renderInParens . toTextBuilder settings) a+  parser settings =+    asum+      [ do+          Parsers.keyword "interval"+          Parser.endHead+          asum+            [ ConstIntervalSimpleTypename <$> Right <$> (Parsers.space *> Parsers.inParens (parser settings)),+              ConstIntervalSimpleTypename <$> Left <$> optional (Parsers.space *> parser settings)+            ],+        ConstDatetimeSimpleTypename <$> parser settings,+        NumericSimpleTypename <$> parser settings,+        BitSimpleTypename <$> parser settings,+        CharacterSimpleTypename <$> parser settings,+        GenericTypeSimpleTypename <$> parser settings+      ]++instance Qc.Arbitrary SimpleTypename where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ GenericTypeSimpleTypename <$> Qc.arbitrary,+        NumericSimpleTypename <$> Qc.arbitrary,+        BitSimpleTypename <$> Qc.arbitrary,+        CharacterSimpleTypename <$> Qc.arbitrary,+        ConstDatetimeSimpleTypename <$> Qc.arbitrary,+        ConstIntervalSimpleTypename <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SortBy.hs view
@@ -0,0 +1,60 @@+module PostgresqlSyntax.Ast.SortBy where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr, filteredParser)+import PostgresqlSyntax.Ast.AscDesc+import PostgresqlSyntax.Ast.NullsOrder+import PostgresqlSyntax.Ast.QualAllOp+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, sortBy, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- sortby:+--   | a_expr USING qual_all_Op opt_nulls_order+--   | a_expr opt_asc_desc opt_nulls_order+-- @+data SortBy+  = UsingSortBy AExpr QualAllOp (Maybe NullsOrder)+  | AscDescSortBy AExpr (Maybe AscDesc) (Maybe NullsOrder)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SortBy where+  toTextBuilder settings = \case+    UsingSortBy a b c -> toTextBuilder settings a <> " USING " <> toTextBuilder settings b <> TextBuilders.suffixMaybe (toTextBuilder settings) c+    AscDescSortBy a b c -> toTextBuilder settings a <> TextBuilders.suffixMaybe (toTextBuilder settings) b <> TextBuilders.suffixMaybe (toTextBuilder settings) c+  parser settings = do+    -- gram.y:14056 sortby. Of the four words that can terminate this+    -- a_expr, only NULLS is unreserved (kwlist.h:315) and therefore a+    -- legal ColId; USING/ASC/DESC are reserved (kwlist.h:496,47,138) and+    -- can never be absorbed. Postgres disambiguates NULLS with a+    -- two-token lexer lookahead (NULLS_LA, gram.y:864); this exclusion is+    -- the coarser recursive-descent equivalent.+    a <- filteredParser settings ["nulls"]+    asum+      [ do+          Parsers.space1+          Parsers.keyword "using"+          Parsers.space1+          Parser.endHead+          b <- parser settings+          c <- optional (Parsers.space1 *> parser settings)+          return (UsingSortBy a b c),+        do+          b <- optional (Parsers.space1 *> parser settings)+          c <- optional (Parsers.space1 *> parser settings)+          return (AscDescSortBy a b c)+      ]++instance Qc.Arbitrary SortBy where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ UsingSortBy <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary <*> Qc.arbitrary,+        AscDescSortBy <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SortClause.hs view
@@ -0,0 +1,35 @@+module PostgresqlSyntax.Ast.SortClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.SortBy+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, sortBy, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- sort_clause:+--   |  ORDER BY sortby_list+--+-- sortby_list:+--   |  sortby+--   |  sortby_list ',' sortby+-- @+newtype SortClause = SortClause (NonEmpty SortBy)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SortClause where+  toTextBuilder settings (SortClause a) = "ORDER BY " <> TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = do+    Parsers.keyphrase "order by"+    Parser.endHead+    Parsers.space1+    SortClause <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary SortClause where+  shrink = Qc.genericShrink+  arbitrary = SortClause <$> Gens.nonEmptyUpTo 7 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/SubType.hs view
@@ -0,0 +1,33 @@+module PostgresqlSyntax.Ast.SubType where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- sub_type:+--   | ANY+--   | SOME+--   | ALL+-- @+data SubType = AnySubType | SomeSubType | AllSubType+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst SubType where+  toTextBuilder _settings = \case+    AnySubType -> "ANY"+    SomeSubType -> "SOME"+    AllSubType -> "ALL"+  parser _settings =+    asum+      [ AnySubType <$ Parsers.keyword "any",+        SomeSubType <$ Parsers.keyword "some",+        AllSubType <$ Parsers.keyword "all"+      ]++instance Qc.Arbitrary SubType where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/SubqueryOp.hs view
@@ -0,0 +1,53 @@+module PostgresqlSyntax.Ast.SubqueryOp where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AllOp+import PostgresqlSyntax.Ast.AnyOperator+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- subquery_Op:+--   | all_Op+--   | OPERATOR '(' any_operator ')'+--   | LIKE+--   | NOT_LA LIKE+--   | ILIKE+--   | NOT_LA ILIKE+-- @+data SubqueryOp+  = AllSubqueryOp AllOp+  | AnySubqueryOp AnyOperator+  | LikeSubqueryOp Bool+  | IlikeSubqueryOp Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SubqueryOp where+  toTextBuilder settings = \case+    AllSubqueryOp a -> toTextBuilder settings a+    AnySubqueryOp a -> "OPERATOR " <> TextBuilders.renderInParens (toTextBuilder settings a)+    LikeSubqueryOp a -> bool "" "NOT " a <> "LIKE"+    IlikeSubqueryOp a -> bool "" "NOT " a <> "ILIKE"+  parser settings =+    asum+      [ AnySubqueryOp <$> (Parsers.keyword "operator" *> Parsers.space *> Parser.endHead *> Parsers.inParens (parser settings)),+        do+          a <- Parsers.trueIfPresent (Parsers.keyword "not" *> Parsers.space1)+          LikeSubqueryOp a <$ Parsers.keyword "like" <|> IlikeSubqueryOp a <$ Parsers.keyword "ilike",+        AllSubqueryOp <$> parser settings+      ]++instance Qc.Arbitrary SubqueryOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ AllSubqueryOp <$> Qc.arbitrary,+        AnySubqueryOp <$> Qc.arbitrary,+        LikeSubqueryOp <$> Qc.arbitrary,+        IlikeSubqueryOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SubstrList.hs view
@@ -0,0 +1,45 @@+module PostgresqlSyntax.Ast.SubstrList where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.SubstrListFromFor+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- substr_list:+--   | a_expr substr_from substr_for+--   | a_expr substr_for substr_from+--   | a_expr substr_from+--   | a_expr substr_for+--   | expr_list+--   | EMPTY+-- @+data SubstrList+  = ExprSubstrList AExpr SubstrListFromFor+  | ExprListSubstrList ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SubstrList where+  toTextBuilder settings = \case+    ExprSubstrList a b -> toTextBuilder settings a <> " " <> toTextBuilder settings b+    ExprListSubstrList a -> toTextBuilder settings a+  parser settings =+    asum+      [ ExprSubstrList <$> Parser.wrapToHead (parser settings) <*> (Parsers.space1 *> parser settings),+        ExprListSubstrList <$> parser settings+      ]++instance Qc.Arbitrary SubstrList where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprSubstrList <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+        ExprListSubstrList <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SubstrListFromFor.hs view
@@ -0,0 +1,63 @@+module PostgresqlSyntax.Ast.SubstrListFromFor where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+--   | a_expr substr_from substr_for+--   | a_expr substr_for substr_from+--   | a_expr substr_from+--   | a_expr substr_for+-- @+data SubstrListFromFor+  = FromForSubstrListFromFor AExpr AExpr+  | ForFromSubstrListFromFor AExpr AExpr+  | FromSubstrListFromFor AExpr+  | ForSubstrListFromFor AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SubstrListFromFor where+  toTextBuilder settings = \case+    FromForSubstrListFromFor a b -> "FROM " <> toTextBuilder settings a <> " FOR " <> toTextBuilder settings b+    ForFromSubstrListFromFor a b -> "FOR " <> toTextBuilder settings a <> " FROM " <> toTextBuilder settings b+    FromSubstrListFromFor a -> "FROM " <> toTextBuilder settings a+    ForSubstrListFromFor a -> "FOR " <> toTextBuilder settings a+  parser settings =+    asum+      [ do+          a <- substrFrom+          asum+            [ do+                b <- Parsers.space1 *> substrFor+                return (FromForSubstrListFromFor a b),+              return (FromSubstrListFromFor a)+            ],+        do+          a <- substrFor+          asum+            [ do+                b <- Parsers.space1 *> substrFrom+                return (ForFromSubstrListFromFor a b),+              return (ForSubstrListFromFor a)+            ]+      ]+    where+      substrFrom = Parsers.keyword "from" *> Parsers.space1 *> Parser.endHead *> parser settings+      substrFor = Parsers.keyword "for" *> Parsers.space1 *> Parser.endHead *> parser settings++instance Qc.Arbitrary SubstrListFromFor where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ FromForSubstrListFromFor <$> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+        ForFromSubstrListFromFor <$> Gens.downscale Qc.arbitrary <*> Gens.downscale Qc.arbitrary,+        FromSubstrListFromFor <$> Gens.downscale Qc.arbitrary,+        ForSubstrListFromFor <$> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/SymbolicExprBinOp.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.SymbolicExprBinOp where++import PostgresqlSyntax.Ast.MathOp+import PostgresqlSyntax.Ast.QualOp+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++data SymbolicExprBinOp+  = MathSymbolicExprBinOp MathOp+  | QualSymbolicExprBinOp QualOp+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst SymbolicExprBinOp where+  toTextBuilder settings = \case+    MathSymbolicExprBinOp a -> toTextBuilder settings a+    QualSymbolicExprBinOp a -> toTextBuilder settings a+  parser settings =+    QualSymbolicExprBinOp+      <$> parser settings+        <|> MathSymbolicExprBinOp+      <$> parser settings++instance Qc.Arbitrary SymbolicExprBinOp where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ MathSymbolicExprBinOp <$> Qc.arbitrary,+        QualSymbolicExprBinOp <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/TableFuncElement.hs view
@@ -0,0 +1,40 @@+module PostgresqlSyntax.Ast.TableFuncElement where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AnyName+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.Typename+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- TableFuncElement:+--   | ColId Typename opt_collate_clause+-- @+--+-- @opt_collate_clause@ is a bare alias to 'PostgresqlSyntax.Ast.AnyName'.+data TableFuncElement = TableFuncElement Ident Typename (Maybe AnyName)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TableFuncElement where+  toTextBuilder settings (TableFuncElement a b c) = toTextBuilder settings a <> " " <> toTextBuilder settings b <> TextBuilders.suffixMaybe collateClause c+    where+      collateClause a' = "COLLATE " <> toTextBuilder settings a'+  parser settings = do+    a <- Parser.wrapToHead (colId settings)+    Parsers.space1+    b <- parser settings+    c <- optional (Parsers.space1 *> collateClause)+    return (TableFuncElement a b c)+    where+      collateClause = Parsers.keyword "collate" *> Parsers.space1 *> Parser.endHead *> parser settings++instance Qc.Arbitrary TableFuncElement where+  shrink = Qc.genericShrink+  arbitrary = TableFuncElement <$> arbitrary <*> arbitrary <*> Gens.terminatingMaybe arbitrary
+ library-internal/PostgresqlSyntax/Ast/TableFuncElementList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.TableFuncElementList where++import PostgresqlSyntax.Ast.TableFuncElement+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- TableFuncElementList:+--   | TableFuncElement+--   | TableFuncElementList ',' TableFuncElement+-- @+newtype TableFuncElementList = TableFuncElementList (NonEmpty TableFuncElement)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TableFuncElementList where+  toTextBuilder settings (TableFuncElementList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = TableFuncElementList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary TableFuncElementList where+  shrink = Qc.genericShrink+  arbitrary = TableFuncElementList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/TableRef.hs view
@@ -0,0 +1,265 @@+module PostgresqlSyntax.Ast.TableRef where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.AliasClause+import PostgresqlSyntax.Ast.FuncAliasClause+import PostgresqlSyntax.Ast.FuncTable+import PostgresqlSyntax.Ast.JoinMeth+import PostgresqlSyntax.Ast.JoinedTable+import PostgresqlSyntax.Ast.RelationExpr+import {-# SOURCE #-} PostgresqlSyntax.Ast.SelectWithParens (SelectWithParens)+import PostgresqlSyntax.Ast.TablesampleClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, head, many, some, tail, try)+import PostgresqlSyntax.Settings (Settings)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | relation_expr opt_alias_clause+-- | relation_expr opt_alias_clause tablesample_clause+-- | func_table func_alias_clause+-- | LATERAL_P func_table func_alias_clause+-- | xmltable opt_alias_clause+-- | LATERAL_P xmltable opt_alias_clause+-- | select_with_parens opt_alias_clause+-- | LATERAL_P select_with_parens opt_alias_clause+-- | joined_table+-- | '(' joined_table ')' alias_clause+--+-- TODO: Add xmltable+-- @+--+-- 'PostgresqlSyntax.Ast.JoinedTable' and 'PostgresqlSyntax.Ast.JoinMeth'+-- have their own modules for the type declarations, but the actual+-- parsing\/rendering of joined tables is hosted here (and here alone),+-- since it's genuinely mutually recursive with table-ref parsing itself+-- (a @table_ref@ can be a @joined_table@, and a @joined_table@'s branches+-- each embed two @table_ref@s) — see the doc on 'JoinMeth' for why that+-- type's own instance isn't what's used below.+data TableRef+  = -- |+    -- @+    --    | relation_expr opt_alias_clause+    --    | relation_expr opt_alias_clause tablesample_clause+    -- @+    RelationExprTableRef RelationExpr (Maybe AliasClause) (Maybe TablesampleClause)+  | -- |+    -- @+    --    | func_table func_alias_clause+    --    | LATERAL_P func_table func_alias_clause+    -- @+    FuncTableRef Bool FuncTable (Maybe FuncAliasClause)+  | -- |+    -- @+    --    | select_with_parens opt_alias_clause+    --    | LATERAL_P select_with_parens opt_alias_clause+    -- @+    SelectTableRef Bool SelectWithParens (Maybe AliasClause)+  | -- |+    -- @+    --    | joined_table+    --    | '(' joined_table ')' alias_clause+    -- @+    JoinTableRef JoinedTable (Maybe AliasClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TableRef where+  toTextBuilder settings = renderTableRef settings++  parser settings =+    Parser.label "table reference" $+      do+        tr <- nonTrailingTableRef settings+        recur settings tr++-- |+-- Renders a 'TableRef'. Also used, via 'renderJoinedTable', by+-- "PostgresqlSyntax.Ast.JoinedTable"\'s own 'IsAst' instance — see the doc+-- there for why that module doesn't maintain its own copy of this logic.+renderTableRef :: Settings -> TableRef -> TextBuilder+renderTableRef settings = \case+  RelationExprTableRef a b c ->+    TextBuilders.optLexemes+      [ Just (toTextBuilder settings a),+        fmap (toTextBuilder settings) b,+        fmap (toTextBuilder settings) c+      ]+  FuncTableRef a b c ->+    TextBuilders.optLexemes+      [ if a then Just "LATERAL" else Nothing,+        Just (toTextBuilder settings b),+        fmap (toTextBuilder settings) c+      ]+  SelectTableRef a b c ->+    TextBuilders.optLexemes+      [ if a then Just "LATERAL" else Nothing,+        Just (toTextBuilder settings b),+        fmap (toTextBuilder settings) c+      ]+  JoinTableRef a b -> case b of+    Just c -> TextBuilders.renderInParens (renderJoinedTable settings a) <> " " <> toTextBuilder settings c+    Nothing -> renderJoinedTable settings a++-- |+-- Renders a 'PostgresqlSyntax.Ast.JoinedTable.JoinedTable'. This — not+-- "PostgresqlSyntax.Ast.JoinedTable"\'s own 'IsAst' instance — is what+-- actually gets used whenever a joined table is rendered as part of a+-- 'TableRef', since a @table_ref@ and a @joined_table@ are genuinely+-- mutually recursive (a @table_ref@ can be a @joined_table@, and a+-- @joined_table@'s branches each embed two @table_ref@s), and only this+-- module has both in scope non-abstractly at once. Exposed via the+-- 'PostgresqlSyntax.Ast.TableRef.hs-boot' so+-- "PostgresqlSyntax.Ast.JoinedTable" can delegate its own 'IsAst' instance+-- to it, rather than maintaining a second, subtly different copy — see the+-- doc on 'PostgresqlSyntax.Ast.JoinMeth' for why 'JoinMeth'\'s own instance+-- still needs to differ from this one.+renderJoinedTable :: Settings -> JoinedTable -> TextBuilder+renderJoinedTable settings = \case+  InParensJoinedTable a -> TextBuilders.renderInParens (renderJoinedTable settings a)+  MethJoinedTable a b c -> case a of+    CrossJoinMeth -> renderTableRef settings b <> " CROSS JOIN " <> renderTableRef settings c+    QualJoinMeth d e -> renderTableRef settings b <> TextBuilders.suffixMaybe (toTextBuilder settings) d <> " JOIN " <> renderTableRef settings c <> " " <> toTextBuilder settings e+    NaturalJoinMeth d -> renderTableRef settings b <> " NATURAL" <> TextBuilders.suffixMaybe (toTextBuilder settings) d <> " JOIN " <> renderTableRef settings c++recur :: Settings -> TableRef -> Parser TableRef+recur settings tr =+  asum+    [ do+        tr2 <- Parser.wrapToHead (Parsers.space1 *> trailingTableRef settings tr)+        Parser.endHead+        recur settings tr2,+      pure tr+    ]++nonTrailingTableRef :: Settings -> Parser TableRef+nonTrailingTableRef settings =+  asum+    [lateralTableRef <|> Parser.wrapToHead nonLateralTableRef <|> relationExprTableRef <|> joinedTableWithAliasTableRef <|> inParensJoinedTableTableRef]+  where+    relationExprTableRef = do+      relationExpr <- parser settings+      Parser.endHead+      optAliasClause <- optional (Parsers.space1 *> parser settings)+      optTablesampleClause <- optional (Parsers.space1 *> parser settings)+      return (RelationExprTableRef relationExpr optAliasClause optTablesampleClause)+    lateralTableRef = do+      Parsers.keyword "lateral"+      Parsers.space1+      Parser.endHead+      lateralableTableRef True+    nonLateralTableRef = lateralableTableRef False+    lateralableTableRef lateral =+      asum+        [ do+            a <- parser settings+            b <- optional (Parsers.space1 *> parser settings)+            return (FuncTableRef lateral a b),+          do+            select <- parser settings+            optAliasClause <- optional $ Parsers.space1 *> parser settings+            return (SelectTableRef lateral select optAliasClause)+        ]+    inParensJoinedTableTableRef = JoinTableRef <$> inParensJoinedTable settings <*> pure Nothing+    joinedTableWithAliasTableRef = do+      jt <- Parser.wrapToHead (Parsers.inParens (joinedTableParser settings))+      Parsers.space1+      alias <- parser settings+      return (JoinTableRef jt (Just alias))++trailingTableRef :: Settings -> TableRef -> Parser TableRef+trailingTableRef settings tableRef =+  JoinTableRef <$> trailingJoinedTable settings tableRef <*> pure Nothing++-- |+-- Parses a 'PostgresqlSyntax.Ast.JoinedTable.JoinedTable'. See+-- 'renderJoinedTable' for why this — not+-- "PostgresqlSyntax.Ast.JoinedTable"\'s own 'IsAst' instance — is what+-- actually gets used to parse a joined table wherever one can occur inside a+-- 'TableRef'.+joinedTableParser :: Settings -> Parser JoinedTable+joinedTableParser settings =+  headP >>= tailP+  where+    headP =+      asum+        [ do+            tr <- Parser.wrapToHead (nonTrailingTableRef settings)+            Parsers.space1+            trailingJoinedTable settings tr,+          inParensJoinedTable settings+        ]+    tailP jt =+      asum+        [ do+            jt2 <- Parser.wrapToHead (Parsers.space1 *> trailingJoinedTable settings (JoinTableRef jt Nothing))+            Parser.endHead+            tailP jt2,+          pure jt+        ]++-- ==== References+-- @+--   | '(' joined_table ')'+-- @+inParensJoinedTable :: Settings -> Parser JoinedTable+inParensJoinedTable settings = InParensJoinedTable <$> Parsers.inParens (joinedTableParser settings)++-- ==== References+-- @+--   | table_ref CROSS JOIN table_ref+--   | table_ref join_type JOIN table_ref join_qual+--   | table_ref JOIN table_ref join_qual+--   | table_ref NATURAL join_type JOIN table_ref+--   | table_ref NATURAL JOIN table_ref+-- @+trailingJoinedTable :: Settings -> TableRef -> Parser JoinedTable+trailingJoinedTable settings tr1 =+  asum+    [ do+        Parsers.keyphrase "cross join"+        Parser.endHead+        Parsers.space1+        tr2 <- nonTrailingTableRef settings+        return (MethJoinedTable CrossJoinMeth tr1 tr2),+      do+        jt <- joinTypedJoin+        Parser.endHead+        Parsers.space1+        tr2 <- parser settings+        Parsers.space1+        jq <- parser settings+        return (MethJoinedTable (QualJoinMeth jt jq) tr1 tr2),+      do+        Parsers.keyword "natural"+        Parser.endHead+        Parsers.space1+        jt <- joinTypedJoin+        Parsers.space1+        tr2 <- nonTrailingTableRef settings+        return (MethJoinedTable (NaturalJoinMeth jt) tr1 tr2)+    ]+  where+    joinTypedJoin =+      Just+        <$> (parser settings <* Parser.endHead <* Parsers.space1 <* Parsers.keyword "join")+          <|> Nothing+        <$ Parsers.keyword "join"++instance Qc.Arbitrary TableRef where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.sized $ \n ->+      if n <= 1+        then RelationExprTableRef <$> Qc.arbitrary <*> pure Nothing <*> pure Nothing+        else+          Qc.oneof+            [ RelationExprTableRef <$> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary,+              FuncTableRef <$> Qc.arbitrary <*> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary,+              SelectTableRef <$> Qc.arbitrary <*> Gens.downscale Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary,+              JoinTableRef <$> Qc.arbitrary <*> Gens.terminatingMaybe Qc.arbitrary+            ]
+ library-internal/PostgresqlSyntax/Ast/TableRef.hs-boot view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.TableRef where++import {-# SOURCE #-} PostgresqlSyntax.Ast.JoinedTable (JoinedTable)+import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Parser, Show, TextBuilder)+import PostgresqlSyntax.Settings (Settings)+import Test.QuickCheck (Arbitrary)++data TableRef++instance Show TableRef++instance Eq TableRef++instance Ord TableRef++instance Data TableRef++instance IsAst TableRef++instance Arbitrary TableRef++-- | See "PostgresqlSyntax.Ast.TableRef" for the full documentation. The+-- actual rendering logic for 'PostgresqlSyntax.Ast.JoinedTable', exposed so+-- that module's own 'IsAst' instance can delegate to it instead of+-- maintaining a second, subtly different copy.+renderJoinedTable :: Settings -> JoinedTable -> TextBuilder++-- | See "PostgresqlSyntax.Ast.TableRef" for the full documentation. The+-- actual parsing logic for 'PostgresqlSyntax.Ast.JoinedTable', exposed for+-- the same reason as 'renderJoinedTable'.+joinedTableParser :: Settings -> Parser JoinedTable
+ library-internal/PostgresqlSyntax/Ast/TablesampleClause.hs view
@@ -0,0 +1,47 @@+module PostgresqlSyntax.Ast.TablesampleClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.FuncName+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- tablesample_clause:+--   | TABLESAMPLE func_name '(' expr_list ')' opt_repeatable_clause+-- @+--+-- @opt_repeatable_clause@ is a bare alias to 'PostgresqlSyntax.Ast.AExpr'.+data TablesampleClause = TablesampleClause FuncName ExprList (Maybe AExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TablesampleClause where+  toTextBuilder settings (TablesampleClause a b c) =+    "TABLESAMPLE " <> toTextBuilder settings a <> " (" <> toTextBuilder settings b <> ")" <> TextBuilders.suffixMaybe repeatableClause c+    where+      repeatableClause a' = "REPEATABLE (" <> toTextBuilder settings a' <> ")"+  parser settings = do+    Parsers.keyword "tablesample"+    Parsers.space1+    Parser.endHead+    a <- parser settings+    Parsers.space+    b <- Parsers.inParens (parser settings)+    c <- optional (Parsers.space *> repeatableClause)+    return (TablesampleClause a b c)+    where+      repeatableClause = do+        Parsers.keyword "repeatable"+        Parsers.space+        Parsers.inParens (Parser.endHead *> parser settings)++instance Qc.Arbitrary TablesampleClause where+  shrink = Qc.genericShrink+  arbitrary = TablesampleClause <$> arbitrary <*> arbitrary <*> Gens.terminatingMaybe (Gens.downscale arbitrary)
+ library-internal/PostgresqlSyntax/Ast/TargetEl.hs view
@@ -0,0 +1,79 @@+module PostgresqlSyntax.Ast.TargetEl where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import {-# SOURCE #-} qualified PostgresqlSyntax.Ast.AExpr as AExpr+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- target_el:+--   |  a_expr AS ColLabel+--   |  a_expr IDENT+--   |  a_expr+--   |  '*'+-- @+data TargetEl+  = AliasedExprTargetEl AExpr Ident+  | ImplicitlyAliasedExprTargetEl AExpr Ident+  | ExprTargetEl AExpr+  | AsteriskTargetEl+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TargetEl where+  toTextBuilder settings = \case+    AliasedExprTargetEl a b -> toTextBuilder settings a <> " AS " <> toTextBuilder settings b+    ImplicitlyAliasedExprTargetEl a b -> toTextBuilder settings a <> " " <> toTextBuilder settings b+    ExprTargetEl a -> toTextBuilder settings a+    AsteriskTargetEl -> "*"++  parser settings =+    Parser.label "target" $+      asum+        [ do+            expr <- parser settings+            asum+              [ do+                  Parsers.space1+                  asum+                    [ AliasedExprTargetEl expr <$> (Parsers.keyword "as" *> Parsers.space1 *> Parser.endHead *> colLabel),+                      ImplicitlyAliasedExprTargetEl expr <$> parser settings+                    ],+                pure (ExprTargetEl expr)+              ],+          AsteriskTargetEl <$ Parsers.char '*'+        ]+    where+      -- Duplicated from "PostgresqlSyntax.Parsing"'s @colLabel@ (a+      -- bare-aliased 'PostgresqlSyntax.Ast.Ident' whose own, more+      -- permissive parser lives above this module in the dependency+      -- order), mirroring the 'PostgresqlSyntax.Ast.AnyName' precedent.+      colLabel =+        Parser.label "column label" $+          Parsers.keywordNameFromSet UnquotedIdent KeywordSet.keyword+            <|> parser settings++instance Qc.Arbitrary TargetEl where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ pure AsteriskTargetEl,+        AliasedExprTargetEl <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+        -- Unlike 'AliasedExprTargetEl' (separated from its alias by the+        -- reserved @AS@ Parsers.keyword) or 'ExprTargetEl' (followed only by a+        -- comma\/end of list, neither valid @a_expr@ continuations), the+        -- expr here is followed directly by a bare alias identifier with+        -- nothing but a space — exactly the hazard+        -- 'PostgresqlSyntax.Ast.AExpr.isBoundedAExprOperand' guards+        -- against (e.g. rendering an 'PostgresqlSyntax.Ast.AExpr.OrAExpr'+        -- bare here would let its right operand absorb the alias).+        ImplicitlyAliasedExprTargetEl <$> AExpr.safeAExprOperand (Gens.downscale Qc.arbitrary) <*> Qc.arbitrary,+        ExprTargetEl <$> Gens.downscale Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/TargetList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.TargetList where++import PostgresqlSyntax.Ast.TargetEl+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- target_list:+--   | target_el+--   | target_list ',' target_el+-- @+newtype TargetList = TargetList (NonEmpty TargetEl)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TargetList where+  toTextBuilder settings (TargetList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = TargetList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary TargetList where+  shrink = Qc.genericShrink+  arbitrary = TargetList <$> Gens.nonEmptyUpTo 7 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Targeting.hs view
@@ -0,0 +1,65 @@+module PostgresqlSyntax.Ast.Targeting where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.TargetList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- simple_select:+--   |  SELECT opt_all_clause opt_target_list ...+--   |  SELECT distinct_clause target_list ...+--+-- distinct_clause:+--   |  DISTINCT+--   |  DISTINCT ON '(' expr_list ')'+-- @+data Targeting+  = NormalTargeting TargetList+  | AllTargeting (Maybe TargetList)+  | DistinctTargeting (Maybe ExprList) TargetList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Targeting where+  toTextBuilder settings = \case+    NormalTargeting a -> toTextBuilder settings a+    AllTargeting a -> "ALL" <> TextBuilders.suffixMaybe (toTextBuilder settings) a+    DistinctTargeting a b -> "DISTINCT" <> TextBuilders.suffixMaybe onExpressionsClause a <> " " <> toTextBuilder settings b+    where+      onExpressionsClause a = "ON (" <> toTextBuilder settings a <> ")"+  parser settings = distinct <|> allWithTargetList <|> allP <|> normal+    where+      normal = NormalTargeting <$> parser settings+      allWithTargetList = do+        Parsers.keyword "all"+        Parsers.space1+        AllTargeting . Just <$> parser settings+      allP = Parsers.keyword "all" $> AllTargeting Nothing+      distinct = do+        Parsers.keyword "distinct"+        Parsers.space1+        Parser.endHead+        optOn <- optional (onExpressionsClause <* Parsers.space1)+        targetList <- parser settings+        return (DistinctTargeting optOn targetList)+      onExpressionsClause = do+        Parsers.keyword "on"+        Parsers.space1+        Parser.endHead+        ExprList <$> Parsers.inParens (Parsers.sep1 Parsers.commaSeparator (parser settings))++instance Qc.Arbitrary Targeting where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ NormalTargeting <$> Qc.arbitrary,+        AllTargeting <$> Qc.arbitrary,+        DistinctTargeting <$> Gens.terminatingMaybe Qc.arbitrary <*> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/Timezone.hs view
@@ -0,0 +1,30 @@+module PostgresqlSyntax.Ast.Timezone where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_timezone:+--   | WITH_LA TIME ZONE+--   | WITHOUT TIME ZONE+--   | EMPTY+-- @+newtype Timezone = Timezone Bool+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Timezone where+  toTextBuilder _settings (Timezone a) = if a then "WITHOUT TIME ZONE" else "WITH TIME ZONE"+  parser _settings =+    Timezone+      <$> asum+        [ False <$ Parsers.keyphrase "with time zone",+          True <$ Parsers.keyphrase "without time zone"+        ]++instance Qc.Arbitrary Timezone where+  shrink = Qc.genericShrink+  arbitrary = Timezone <$> arbitrary
+ library-internal/PostgresqlSyntax/Ast/TrimList.hs view
@@ -0,0 +1,45 @@+module PostgresqlSyntax.Ast.TrimList where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- trim_list:+--   | a_expr FROM expr_list+--   | FROM expr_list+--   | expr_list+-- @+data TrimList+  = ExprFromExprListTrimList AExpr ExprList+  | FromExprListTrimList ExprList+  | ExprListTrimList ExprList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TrimList where+  toTextBuilder settings = \case+    ExprFromExprListTrimList a b -> toTextBuilder settings a <> " FROM " <> toTextBuilder settings b+    FromExprListTrimList a -> "FROM " <> toTextBuilder settings a+    ExprListTrimList a -> toTextBuilder settings a+  parser settings =+    asum+      [ ExprFromExprListTrimList <$> Parser.wrapToHead (parser settings) <*> (Parsers.space1 *> Parsers.keyword "from" *> Parsers.space1 *> Parser.endHead *> parser settings),+        FromExprListTrimList <$> (Parsers.keyword "from" *> Parsers.space1 *> Parser.endHead *> parser settings),+        ExprListTrimList <$> parser settings+      ]++instance Qc.Arbitrary TrimList where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprFromExprListTrimList <$> Gens.downscale Qc.arbitrary <*> Qc.arbitrary,+        FromExprListTrimList <$> Qc.arbitrary,+        ExprListTrimList <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/TrimModifier.hs view
@@ -0,0 +1,33 @@+module PostgresqlSyntax.Ast.TrimModifier where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+--   | TRIM '(' BOTH trim_list ')'+--   | TRIM '(' LEADING trim_list ')'+--   | TRIM '(' TRAILING trim_list ')'+-- @+data TrimModifier = BothTrimModifier | LeadingTrimModifier | TrailingTrimModifier+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst TrimModifier where+  toTextBuilder _settings = \case+    BothTrimModifier -> "BOTH"+    LeadingTrimModifier -> "LEADING"+    TrailingTrimModifier -> "TRAILING"+  parser _settings =+    BothTrimModifier+      <$ Parsers.keyword "both"+        <|> LeadingTrimModifier+      <$ Parsers.keyword "leading"+        <|> TrailingTrimModifier+      <$ Parsers.keyword "trailing"++instance Qc.Arbitrary TrimModifier where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/TypeList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.TypeList where++import PostgresqlSyntax.Ast.Typename+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- type_list:+--   | Typename+--   | type_list ',' Typename+-- @+newtype TypeList = TypeList (NonEmpty Typename)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TypeList where+  toTextBuilder settings (TypeList a) = TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = TypeList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary TypeList where+  shrink = Qc.genericShrink+  arbitrary = TypeList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/Typename.hs view
@@ -0,0 +1,46 @@+module PostgresqlSyntax.Ast.Typename where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.SimpleTypename+import PostgresqlSyntax.Ast.TypenameArrayDimensions+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (resolveNullabilityMarkers)+import qualified Test.QuickCheck as Qc++data Typename+  = Typename+      Bool+      SimpleTypename+      Bool+      (Maybe (TypenameArrayDimensions, Bool))+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Typename where+  toTextBuilder settings (Typename setof base typeNullable arrayDims) =+    bool "" "SETOF " setof+      <> toTextBuilder settings base+      <> marker typeNullable+      <> foldMap renderArray arrayDims+    where+      markersOn = resolveNullabilityMarkers settings+      marker flag = if markersOn && flag then "?" else mempty+      renderArray (dims, flag) = toTextBuilder settings dims <> marker flag+  parser settings = do+    setof <- option False (Parsers.keyword "setof" *> Parsers.space1 $> True)+    base <- parser settings+    Parser.endHead+    let marker = if resolveNullabilityMarkers settings then Parsers.trueIfPresent (Parsers.char '?') else pure False+    typeNullable <- marker+    arrayDims <- optional $ do+      dims <- parser settings+      flag <- marker+      pure (dims, flag)+    pure (Typename setof base typeNullable arrayDims)++instance Qc.Arbitrary Typename where+  shrink = Qc.genericShrink+  arbitrary = Typename <$> arbitrary <*> arbitrary <*> pure False <*> ((\a -> (,) a False) <$$> arbitrary)+    where+      (<$$>) = fmap . fmap
+ library-internal/PostgresqlSyntax/Ast/TypenameArrayDimensions.hs view
@@ -0,0 +1,45 @@+module PostgresqlSyntax.Ast.TypenameArrayDimensions where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ArrayBounds+import PostgresqlSyntax.Ast.Iconst+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- Part of the Typename specification responsible for the choice between the following:+--   | opt_array_bounds+--   | ARRAY '[' Iconst ']'+--   | ARRAY+-- @+data TypenameArrayDimensions+  = BoundsTypenameArrayDimensions ArrayBounds+  | ExplicitTypenameArrayDimensions (Maybe Iconst)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst TypenameArrayDimensions where+  toTextBuilder settings = \case+    BoundsTypenameArrayDimensions a -> toTextBuilder settings a+    ExplicitTypenameArrayDimensions a -> " ARRAY" <> foldMap (TextBuilders.renderInBrackets . toTextBuilder settings) a+  parser settings =+    asum+      [ do+          Parsers.space1+          Parsers.keyword "array"+          Parser.endHead+          ExplicitTypenameArrayDimensions <$> optional (Parsers.space *> Parsers.inBrackets (parser settings)),+        BoundsTypenameArrayDimensions <$> (Parsers.space *> parser settings)+      ]++instance Qc.Arbitrary TypenameArrayDimensions where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ BoundsTypenameArrayDimensions <$> Qc.arbitrary,+        ExplicitTypenameArrayDimensions <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/UpdateStmt.hs view
@@ -0,0 +1,66 @@+module PostgresqlSyntax.Ast.UpdateStmt where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.FromClause+import PostgresqlSyntax.Ast.RelationExprOptAlias (RelationExprOptAlias)+import qualified PostgresqlSyntax.Ast.RelationExprOptAlias as RelationExprOptAlias+import PostgresqlSyntax.Ast.ReturningClause+import PostgresqlSyntax.Ast.SetClauseList+import PostgresqlSyntax.Ast.WhereOrCurrentClause+import {-# SOURCE #-} PostgresqlSyntax.Ast.WithClause (WithClause)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- UpdateStmt:+--   | opt_with_clause UPDATE relation_expr_opt_alias+--       SET set_clause_list+--       from_clause+--       where_or_current_clause+--       returning_clause+-- @+data UpdateStmt = UpdateStmt (Maybe WithClause) RelationExprOptAlias SetClauseList (Maybe FromClause) (Maybe WhereOrCurrentClause) (Maybe ReturningClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst UpdateStmt where+  toTextBuilder settings (UpdateStmt a b c d e f) =+    TextBuilders.prefixMaybe (toTextBuilder settings) a+      <> "UPDATE "+      <> toTextBuilder settings b+      <> " "+      <> "SET "+      <> toTextBuilder settings c+      <> TextBuilders.suffixMaybe (toTextBuilder settings) d+      <> TextBuilders.suffixMaybe (toTextBuilder settings) e+      <> TextBuilders.suffixMaybe (toTextBuilder settings) f+  parser settings = do+    a <- optional (Parser.wrapToHead (parser settings) <* Parsers.space1)+    Parsers.keyword "update"+    Parsers.space1+    Parser.endHead+    b <- RelationExprOptAlias.customizedParser settings ["set"]+    Parsers.space1+    Parsers.keyword "set"+    Parsers.space1+    c <- parser settings+    d <- optional (Parsers.space1 *> parser settings)+    e <- optional (Parsers.space1 *> parser settings)+    f <- optional (Parsers.space1 *> parser settings)+    return (UpdateStmt a b c d e f)++instance Qc.Arbitrary UpdateStmt where+  shrink = Qc.genericShrink+  arbitrary =+    UpdateStmt+      <$> Gens.terminatingMaybe (Gens.downscale Qc.arbitrary)+      <*> Qc.arbitrary+      <*> Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/UsingClause.hs view
@@ -0,0 +1,28 @@+module PostgresqlSyntax.Ast.UsingClause where++import PostgresqlSyntax.Ast.FromList+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- using_clause:+--   |  USING from_list+--   |  /*EMPTY*/+-- @+newtype UsingClause = UsingClause FromList+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst UsingClause where+  toTextBuilder settings (UsingClause a) = "USING " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "using"+    Parsers.space1+    UsingClause <$> parser settings++instance Qc.Arbitrary UsingClause where+  shrink = Qc.genericShrink+  arbitrary = UsingClause <$> Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/ValuesClause.hs view
@@ -0,0 +1,40 @@+module PostgresqlSyntax.Ast.ValuesClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ExprList+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- values_clause:+--   |  VALUES '(' expr_list ')'+--   |  values_clause ',' '(' expr_list ')'+-- @+newtype ValuesClause = ValuesClause (NonEmpty ExprList)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst ValuesClause where+  toTextBuilder settings (ValuesClause a) = "VALUES " <> TextBuilders.commaNonEmpty (TextBuilders.renderInParens . toTextBuilder settings) a+  parser settings = do+    Parsers.keyword "values"+    Parsers.space+    ValuesClause <$> Parsers.sep1 Parsers.commaSeparator row+    where+      row = do+        Parsers.char '('+        Parser.endHead+        Parsers.space+        a <- ExprList <$> Parsers.sep1 Parsers.commaSeparator (parser settings)+        Parsers.space+        Parsers.char ')'+        return a++instance Qc.Arbitrary ValuesClause where+  shrink = Qc.genericShrink+  arbitrary = ValuesClause <$> Gens.nonEmptyUpTo 7 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/VerbalExprBinOp.hs view
@@ -0,0 +1,38 @@+module PostgresqlSyntax.Ast.VerbalExprBinOp where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+--   | LIKE+--   | NOT_LA LIKE+--   | ILIKE+--   | NOT_LA ILIKE+--   | SIMILAR TO+--   | NOT_LA SIMILAR TO+-- @+data VerbalExprBinOp+  = LikeVerbalExprBinOp+  | IlikeVerbalExprBinOp+  | SimilarToVerbalExprBinOp+  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)++instance IsAst VerbalExprBinOp where+  toTextBuilder _settings = \case+    LikeVerbalExprBinOp -> "LIKE"+    IlikeVerbalExprBinOp -> "ILIKE"+    SimilarToVerbalExprBinOp -> "SIMILAR TO"+  parser _settings =+    asum+      [ LikeVerbalExprBinOp <$ Parsers.keyword "like",+        IlikeVerbalExprBinOp <$ Parsers.keyword "ilike",+        SimilarToVerbalExprBinOp <$ Parsers.keyphrase "similar to"+      ]++instance Qc.Arbitrary VerbalExprBinOp where+  shrink = Qc.genericShrink+  arbitrary = Qc.elements [minBound .. maxBound]
+ library-internal/PostgresqlSyntax/Ast/WhenClause.hs view
@@ -0,0 +1,35 @@+module PostgresqlSyntax.Ast.WhenClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- when_clause:+--   |  WHEN a_expr THEN a_expr+-- @+data WhenClause = WhenClause AExpr AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WhenClause where+  toTextBuilder settings (WhenClause a b) = "WHEN " <> toTextBuilder settings a <> " THEN " <> toTextBuilder settings b+  parser settings = do+    Parsers.keyword "when"+    Parsers.space1+    Parser.endHead+    a <- parser settings+    Parsers.space1+    Parsers.keyword "then"+    Parsers.space1+    b <- parser settings+    return (WhenClause a b)++instance Qc.Arbitrary WhenClause where+  shrink = Qc.genericShrink+  arbitrary = WhenClause <$> Gens.downscale arbitrary <*> Gens.downscale arbitrary
+ library-internal/PostgresqlSyntax/Ast/WhenClauseList.hs view
@@ -0,0 +1,27 @@+module PostgresqlSyntax.Ast.WhenClauseList where++import PostgresqlSyntax.Ast.WhenClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- when_clause_list:+--   | when_clause+--   | when_clause_list when_clause+-- @+newtype WhenClauseList = WhenClauseList (NonEmpty WhenClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WhenClauseList where+  toTextBuilder settings (WhenClauseList a) = TextBuilders.spaceNonEmpty (toTextBuilder settings) a+  parser settings = WhenClauseList <$> Parsers.sep1 Parsers.space1 (parser settings)++instance Qc.Arbitrary WhenClauseList where+  shrink = Qc.genericShrink+  arbitrary = WhenClauseList <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/WhereClause.hs view
@@ -0,0 +1,31 @@+module PostgresqlSyntax.Ast.WhereClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- where_clause:+--   |  WHERE a_expr+--   |  /*EMPTY*/+-- @+newtype WhereClause = WhereClause AExpr+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WhereClause where+  toTextBuilder settings (WhereClause a) = "WHERE " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "where"+    Parsers.space1+    Parser.endHead+    WhereClause <$> parser settings++instance Qc.Arbitrary WhereClause where+  shrink = Qc.genericShrink+  arbitrary = WhereClause <$> Gens.downscale Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/WhereOrCurrentClause.hs view
@@ -0,0 +1,52 @@+module PostgresqlSyntax.Ast.WhereOrCurrentClause where++import qualified HeadedMegaparsec as Parser+import {-# SOURCE #-} PostgresqlSyntax.Ast.AExpr (AExpr)+import PostgresqlSyntax.Ast.Ident+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- | WHERE a_expr+-- | WHERE CURRENT_P OF cursor_name+-- | /*EMPTY*/+-- @+--+-- @cursor_name@ is a bare alias to 'PostgresqlSyntax.Ast.Ident'.+data WhereOrCurrentClause+  = ExprWhereOrCurrentClause AExpr+  | CursorWhereOrCurrentClause Ident+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WhereOrCurrentClause where+  toTextBuilder settings = \case+    ExprWhereOrCurrentClause a -> "WHERE " <> toTextBuilder settings a+    CursorWhereOrCurrentClause a -> "WHERE CURRENT OF " <> toTextBuilder settings a+  parser settings = do+    Parsers.keyword "where"+    Parsers.space1+    Parser.endHead+    asum+      [ do+          Parsers.keyword "current"+          Parsers.space1+          Parsers.keyword "of"+          Parsers.space1+          Parser.endHead+          a <- colId settings+          return (CursorWhereOrCurrentClause a),+        ExprWhereOrCurrentClause <$> parser settings+      ]++instance Qc.Arbitrary WhereOrCurrentClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.oneof+      [ ExprWhereOrCurrentClause <$> Gens.downscale Qc.arbitrary,+        CursorWhereOrCurrentClause <$> Qc.arbitrary+      ]
+ library-internal/PostgresqlSyntax/Ast/WindowClause.hs view
@@ -0,0 +1,32 @@+module PostgresqlSyntax.Ast.WindowClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.WindowDefinition+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude hiding (filter, many, some, try)+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- window_clause:+--   |  WINDOW window_definition_list+--   |  /*EMPTY*/+-- @+newtype WindowClause = WindowClause (NonEmpty WindowDefinition)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WindowClause where+  toTextBuilder settings (WindowClause a) = "WINDOW " <> TextBuilders.commaNonEmpty (toTextBuilder settings) a+  parser settings = do+    Parsers.keyword "window"+    Parser.endHead+    Parsers.space1+    WindowClause <$> Parsers.sep1 Parsers.commaSeparator (parser settings)++instance Qc.Arbitrary WindowClause where+  shrink = Qc.genericShrink+  arbitrary = WindowClause <$> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/WindowDefinition.hs view
@@ -0,0 +1,26 @@+module PostgresqlSyntax.Ast.WindowDefinition where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.WindowSpecification+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- window_definition:+--   |  ColId AS window_specification+-- @+data WindowDefinition = WindowDefinition Ident WindowSpecification+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WindowDefinition where+  toTextBuilder settings (WindowDefinition a b) = toTextBuilder settings a <> " AS " <> toTextBuilder settings b+  parser settings = WindowDefinition <$> (colId settings <* Parsers.space1 <* Parsers.keyword "as" <* Parsers.space1 <* Parser.endHead) <*> parser settings++instance Qc.Arbitrary WindowDefinition where+  shrink = Qc.genericShrink+  arbitrary = WindowDefinition <$> arbitrary <*> arbitrary
+ library-internal/PostgresqlSyntax/Ast/WindowExclusionClause.hs view
@@ -0,0 +1,49 @@+module PostgresqlSyntax.Ast.WindowExclusionClause where++import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- opt_window_exclusion_clause:+--   |  EXCLUDE CURRENT_P ROW+--   |  EXCLUDE GROUP_P+--   |  EXCLUDE TIES+--   |  EXCLUDE NO OTHERS+--   |  EMPTY+-- @+data WindowExclusionClause+  = CurrentRowWindowExclusionClause+  | GroupWindowExclusionClause+  | TiesWindowExclusionClause+  | NoOthersWindowExclusionClause+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WindowExclusionClause where+  toTextBuilder _settings = \case+    CurrentRowWindowExclusionClause -> "EXCLUDE CURRENT ROW"+    GroupWindowExclusionClause -> "EXCLUDE GROUP"+    TiesWindowExclusionClause -> "EXCLUDE TIES"+    NoOthersWindowExclusionClause -> "EXCLUDE NO OTHERS"+  parser _settings =+    CurrentRowWindowExclusionClause+      <$ Parsers.keyphrase "exclude current row"+        <|> GroupWindowExclusionClause+      <$ Parsers.keyphrase "exclude group"+        <|> TiesWindowExclusionClause+      <$ Parsers.keyphrase "exclude ties"+        <|> NoOthersWindowExclusionClause+      <$ Parsers.keyphrase "exclude no others"++instance Qc.Arbitrary WindowExclusionClause where+  shrink = Qc.genericShrink+  arbitrary =+    Qc.elements+      [ CurrentRowWindowExclusionClause,+        GroupWindowExclusionClause,+        TiesWindowExclusionClause,+        NoOthersWindowExclusionClause+      ]
+ library-internal/PostgresqlSyntax/Ast/WindowSpecification.hs view
@@ -0,0 +1,79 @@+module PostgresqlSyntax.Ast.WindowSpecification where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.ExprList+import PostgresqlSyntax.Ast.FrameClause+import PostgresqlSyntax.Ast.Ident+import PostgresqlSyntax.Ast.SortClause+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- window_specification:+--   |  '(' opt_existing_window_name opt_partition_clause+--             opt_sort_clause opt_frame_clause ')'+--+-- opt_existing_window_name:+--   |  ColId+--   |  EMPTY+--+-- opt_partition_clause:+--   |  PARTITION BY expr_list+--   |  EMPTY+-- @+--+-- @existing_window_name@ and @partition_clause@ are bare aliases to+-- 'PostgresqlSyntax.Ast.Ident' (ColId) and 'PostgresqlSyntax.Ast.ExprList'+-- respectively.+data WindowSpecification = WindowSpecification (Maybe Ident) (Maybe ExprList) (Maybe SortClause) (Maybe FrameClause)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WindowSpecification where+  toTextBuilder settings (WindowSpecification a b c d) =+    TextBuilders.renderInParens $+      TextBuilders.optLexemes+        [ fmap (toTextBuilder settings) a,+          fmap (mappend "PARTITION BY " . toTextBuilder settings) b,+          fmap (toTextBuilder settings) c,+          fmap (toTextBuilder settings) d+        ]+  parser settings =+    Parsers.inParens $+      asum+        [ do+            a <- parser settings+            return (WindowSpecification Nothing Nothing Nothing (Just a)),+          do+            a <- parser settings+            b <- optional (Parsers.space1 *> parser settings)+            return (WindowSpecification Nothing Nothing (Just a) b),+          do+            a <- partitionByClause+            b <- optional (Parsers.space1 *> parser settings)+            c <- optional (Parsers.space1 *> parser settings)+            return (WindowSpecification Nothing (Just a) b c),+          do+            a <- colId settings+            b <- optional (Parsers.space1 *> partitionByClause)+            c <- optional (Parsers.space1 *> parser settings)+            d <- optional (Parsers.space1 *> parser settings)+            return (WindowSpecification (Just a) b c d),+          pure (WindowSpecification Nothing Nothing Nothing Nothing)+        ]+    where+      partitionByClause = Parsers.keyphrase "partition by" *> Parsers.space1 *> Parser.endHead *> (ExprList <$> Parsers.sep1 Parsers.commaSeparator (parser settings))++instance Qc.Arbitrary WindowSpecification where+  shrink = Qc.genericShrink+  arbitrary =+    WindowSpecification+      <$> Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary+      <*> Gens.terminatingMaybe Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/WithClause.hs view
@@ -0,0 +1,36 @@+module PostgresqlSyntax.Ast.WithClause where++import qualified HeadedMegaparsec as Parser+import PostgresqlSyntax.Ast.CommonTableExpr (CommonTableExpr)+import qualified PostgresqlSyntax.Helpers.Gens as Gens+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.TextBuilders as TextBuilders+import PostgresqlSyntax.IsAst+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- ==== References+-- @+-- with_clause:+--   |  WITH cte_list+--   |  WITH_LA cte_list+--   |  WITH RECURSIVE cte_list+-- @+data WithClause = WithClause Bool (NonEmpty CommonTableExpr)+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst WithClause where+  toTextBuilder settings (WithClause a b) =+    "WITH " <> bool "" "RECURSIVE " a <> TextBuilders.commaNonEmpty (toTextBuilder settings) b+  parser settings = Parser.label "with clause" $ do+    Parsers.keyword "with"+    Parsers.space1+    Parser.endHead+    recursive <- option False (True <$ Parsers.keyword "recursive" <* Parsers.space1)+    cteList <- Parsers.sep1 Parsers.commaSeparator (parser settings)+    return (WithClause recursive cteList)++instance Qc.Arbitrary WithClause where+  shrink = Qc.genericShrink+  arbitrary = WithClause <$> arbitrary <*> Gens.nonEmptyUpTo 6 Qc.arbitrary
+ library-internal/PostgresqlSyntax/Ast/WithClause.hs-boot view
@@ -0,0 +1,19 @@+module PostgresqlSyntax.Ast.WithClause where++import PostgresqlSyntax.IsAst (IsAst)+import PostgresqlSyntax.Prelude (Data, Eq, Ord, Show)+import Test.QuickCheck (Arbitrary)++data WithClause++instance Show WithClause++instance Eq WithClause++instance Ord WithClause++instance Data WithClause++instance IsAst WithClause++instance Arbitrary WithClause
+ library-internal/PostgresqlSyntax/Ast/Xconst.hs view
@@ -0,0 +1,34 @@+module PostgresqlSyntax.Ast.Xconst where++import qualified Data.Text as Text+import qualified HeadedMegaparsec as Parser+import qualified PostgresqlSyntax.Helpers.Parsers as Parsers+import qualified PostgresqlSyntax.Helpers.Shrinks as Shrinks+import PostgresqlSyntax.IsAst+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc+import qualified TextBuilder++-- |+-- ==== References+-- @+-- XCONST+-- @+newtype Xconst = Xconst Text+  deriving (Show, Generic, Eq, Ord, Data)++instance IsAst Xconst where+  toTextBuilder _settings (Xconst a) = "X'" <> TextBuilder.text a <> "'"+  parser _settings = Parser.label "hex literal" $ do+    Parsers.string' "x'"+    Parser.endHead+    a <- Parsers.takeWhile1P (Just "Hex digit") Predicate.hexDigit+    Parsers.char '\''+    return (Xconst a)++instance Qc.Arbitrary Xconst where+  shrink (Xconst a) = Xconst <$> Shrinks.nonEmptyText a+  arbitrary = do+    len <- Qc.choose (1, 100)+    Xconst . Text.pack <$> Qc.vectorOf len (Qc.elements "0123456789abcdefABCDEF")
+ library-internal/PostgresqlSyntax/CharSet.hs view
@@ -0,0 +1,21 @@+module PostgresqlSyntax.CharSet where++import qualified Data.Text as Text+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude++{-# NOINLINE symbolicBinOp #-}+symbolicBinOp :: HashSet Char+symbolicBinOp = KeywordSet.symbolicBinOp & toList & mconcat & Text.unpack & fromList++{-# NOINLINE hexDigit #-}+hexDigit :: HashSet Char+hexDigit = fromList "0123456789abcdefABCDEF"++{-# NOINLINE op #-}+op :: HashSet Char+op = fromList "+-*/<>=~!@#%^&|`?"++{-# NOINLINE prohibitionLiftingOp #-}+prohibitionLiftingOp :: HashSet Char+prohibitionLiftingOp = fromList "~!@#%^&|`?"
+ library-internal/PostgresqlSyntax/Extras/Error.hs view
@@ -0,0 +1,40 @@+-- |+-- Generic helpers for Error handling in HeadedMegaparsec.+module PostgresqlSyntax.Extras.Error where++import PostgresqlSyntax.Prelude hiding (head)+import Text.Megaparsec++-- | Render all Megaparsec parsing errors as a list of position ('Text.Megaparsec.SourcePos') and messages.+errorBundlePrettyStruct ::+  forall s e.+  ( VisualStream s,+    TraversableStream s,+    ShowErrorComponent e+  ) =>+  -- | Parse error bundle to display+  ParseErrorBundle s e ->+  -- | Textual rendition of the bundle+  NonEmpty (SourcePos, String)+errorBundlePrettyStruct ParseErrorBundle {..} =+  fst $ attachSourcePosAndMessage renderError bundleErrors bundlePosState+  where+    renderError epos e = (epos, parseErrorTextPretty e)++-- | A custom version of 'Text.Megaparsec.attachSourcePos' to provide the NonEmpty list of errors with their position while only traversing the errors list once.+attachSourcePosAndMessage ::+  (TraversableStream s) =>+  -- | Format function for a single 'ParseError' and its 'SourcePos'+  (SourcePos -> ParseError s e -> (SourcePos, String)) ->+  -- | The collection of items+  NonEmpty (ParseError s e) ->+  -- | Initial 'PosState'+  PosState s ->+  -- | The collection with 'SourcePos'es added and the final 'PosState'+  (NonEmpty (SourcePos, String), PosState s)+attachSourcePosAndMessage format xs pst0 =+  swap $ mapAccumL step pst0 xs+  where+    step pst a =+      let pst' = reachOffsetNoLine (errorOffset a) pst+       in (pst', format (pstateSourcePos pst') a)
+ library-internal/PostgresqlSyntax/Extras/HeadedMegaparsec.hs view
@@ -0,0 +1,133 @@+{-# OPTIONS_GHC -Wno-redundant-constraints -Wno-dodgy-imports -Wno-unused-imports #-}++-- |+-- Generic helpers for HeadedMegaparsec.+module PostgresqlSyntax.Extras.HeadedMegaparsec where++import Control.Applicative.Combinators hiding (some)+import Control.Applicative.Combinators.NonEmpty+import qualified Data.Text as Text+import HeadedMegaparsec hiding (string)+import PostgresqlSyntax.Extras.Error (errorBundlePrettyStruct)+import PostgresqlSyntax.Prelude hiding (bit, expr, filter, head, many, option, some, sortBy, tail, try)+import Text.Megaparsec (Parsec, Stream, TraversableStream, VisualStream)+import qualified Text.Megaparsec as Megaparsec+import qualified Text.Megaparsec.Char as MegaparsecChar+import qualified Text.Megaparsec.Char.Lexer as MegaparsecLexer++-- $setup+-- >>> testParser parser = either putStr print . run parser++-- * Executors++run :: (Ord err, VisualStream strm, TraversableStream strm, Megaparsec.ShowErrorComponent err) => HeadedParsec err strm a -> strm -> Either String a+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)++-- |+-- Like 'runParserWithErrorPos' but pairs each error with its+-- ('Megaparsec.SourcePos') in the parsed message instead of a raw offset.+runParserWithSourcePosError :: (Show (Megaparsec.Token strm), Show e, Ord e, VisualStream strm, TraversableStream strm, Megaparsec.ShowErrorComponent e) => HeadedParsec e strm a -> strm -> Either (NonEmpty (Megaparsec.SourcePos, String)) a+runParserWithSourcePosError p s = case runParser p s of+  Left err -> Left (errorBundlePrettyStruct err)+  Right v -> Right v++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) ""++-- |+-- Require the given parser to consume all remaining input (after optional+-- surrounding whitespace), asserting the parse reaches end-of-input.+totally :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm a -> HeadedParsec err strm a+totally p = space *> p <* HeadedMegaparsec.endHead <* space <* eof++-- * Primitives++-- |+-- Lifted megaparsec\'s `Megaparsec.eof`.+eof :: (Ord err, Stream strm) => HeadedParsec err strm ()+eof = parse Megaparsec.eof++-- |+-- Lifted megaparsec\'s `Megaparsec.space`.+space :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm ()+space = parse MegaparsecChar.space++-- |+-- Lifted megaparsec\'s `Megaparsec.space1`.+space1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm ()+space1 = parse MegaparsecChar.space1++-- |+-- Lifted megaparsec\'s `Megaparsec.char`.+char :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => Char -> HeadedParsec err strm Char+char a = parse (MegaparsecChar.char a)++-- |+-- Lifted megaparsec\'s `Megaparsec.char'`.+char' :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => Char -> HeadedParsec err strm Char+char' a = parse (MegaparsecChar.char' a)++-- |+-- Lifted megaparsec\'s `Megaparsec.string`.+string :: (Ord err, Stream strm) => Megaparsec.Tokens strm -> HeadedParsec err strm (Megaparsec.Tokens strm)+string = parse . MegaparsecChar.string++-- |+-- Lifted megaparsec\'s `Megaparsec.string'`.+string' :: (Ord err, Stream strm, FoldCase (Megaparsec.Tokens strm)) => Megaparsec.Tokens strm -> HeadedParsec err strm (Megaparsec.Tokens strm)+string' = parse . MegaparsecChar.string'++-- |+-- Lifted megaparsec\'s `Megaparsec.takeWhileP`.+takeWhileP :: (Ord err, Stream strm) => Maybe String -> (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Tokens strm)+takeWhileP label predicate = parse (Megaparsec.takeWhileP label predicate)++-- |+-- Lifted megaparsec\'s `Megaparsec.takeWhile1P`.+takeWhile1P :: (Ord err, Stream strm) => Maybe String -> (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Tokens strm)+takeWhile1P label predicate = parse (Megaparsec.takeWhile1P label predicate)++satisfy :: (Ord err, Stream strm) => (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Token strm)+satisfy = parse . Megaparsec.satisfy++decimal :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char, Integral decimal) => HeadedParsec err strm decimal+decimal = parse MegaparsecLexer.decimal++float :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char, RealFloat float) => HeadedParsec err strm float+float = parse MegaparsecLexer.float++-- * Combinators++sep1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm separtor -> HeadedParsec err strm a -> HeadedParsec err strm (NonEmpty a)+sep1 separator parser = do+  head <- parser+  endHead+  tail <- many $ separator *> parser+  return (head :| tail)++sepEnd1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm separator -> HeadedParsec err strm end -> HeadedParsec err strm el -> HeadedParsec err strm (NonEmpty el, end)+sepEnd1 sepP endP elP = do+  headEl <- elP+  let loop !list = do+        _ <- sepP+        asum+          [ do+              end <- endP+              return (headEl :| reverse list, end),+            do+              el <- elP+              loop (el : list)+          ]+   in loop []++notFollowedBy :: (Ord err, Stream strm) => HeadedParsec err strm a -> HeadedParsec err strm ()+notFollowedBy a = parse (Megaparsec.notFollowedBy (toParsec a))
+ library-internal/PostgresqlSyntax/Extras/NonEmpty.hs view
@@ -0,0 +1,33 @@+{-# OPTIONS_GHC -Wno-dodgy-imports #-}++module PostgresqlSyntax.Extras.NonEmpty where++import Data.List.NonEmpty+import PostgresqlSyntax.Prelude hiding (cons, fromList, head, init, last, reverse, tail, uncons)++-- |+-- >>> intersperseFoldMap ", " id (fromList ["a"])+-- "a"+--+-- >>> intersperseFoldMap ", " id (fromList ["a", "b", "c"])+-- "a, b, c"+intersperseFoldMap :: (Monoid m) => m -> (a -> m) -> NonEmpty a -> m+intersperseFoldMap a b (c :| d) = b c <> foldMap (mappend a . b) d++unsnoc :: NonEmpty a -> (Maybe (NonEmpty a), a)+unsnoc =+  let build1 = \case+        a :| b -> build2 a b+      build2 a = \case+        b : c -> build3 b (a :| []) c+        _ -> (Nothing, a)+      build3 a b = \case+        c : d -> build3 c (cons a b) d+        _ -> (Just (reverse b), a)+   in build1++consAndUnsnoc :: a -> NonEmpty a -> (NonEmpty a, a)+consAndUnsnoc a b = case unsnoc b of+  (c, d) -> case c of+    Just e -> (cons a e, d)+    Nothing -> (pure a, d)
+ library-internal/PostgresqlSyntax/Extras/TextBuilder.hs view
@@ -0,0 +1,16 @@+module PostgresqlSyntax.Extras.TextBuilder where++import PostgresqlSyntax.Prelude+import TextBuilder++char7 :: Char -> TextBuilder+char7 = char++intDec :: Int -> TextBuilder+intDec = decimal++int64Dec :: Int64 -> TextBuilder+int64Dec = decimal++doubleDec :: Double -> TextBuilder+doubleDec = fromString . show
+ library-internal/PostgresqlSyntax/Helpers/Gens.hs view
@@ -0,0 +1,51 @@+module PostgresqlSyntax.Helpers.Gens where++import PostgresqlSyntax.Prelude+import Test.QuickCheck++downscale :: Gen a -> Gen a+downscale = scale (`div` 2)++recursive :: Gen a -> Gen a -> Gen a+recursive nonRecursiveGen recursiveGen = sized $ \size ->+  if size <= 1+    then nonRecursiveGen+    else downscale recursiveGen++oneofRec ::+  (Arbitrary a) =>+  [Gen a] ->+  [Gen a] ->+  Gen a+oneofRec nonRecursiveGens recursiveGens = sized $ \size ->+  if size <= 1+    then oneof nonRecursiveGens+    else+      frequency+        [ (1, oneof nonRecursiveGens),+          (3, downscale (oneof recursiveGens))+        ]++-- | Generate a non-empty list of at most @n + 1@ elements, splitting the size+-- budget across them.+--+-- The split is what keeps growth bounded: generating every element at the+-- undiminished size would multiply the subtree's cost by the list length at no+-- size cost, and those multipliers compound through the AST.+nonEmptyUpTo :: Int -> Gen a -> Gen (NonEmpty a)+nonEmptyUpTo n gen = sized $ \size -> do+  -- The 'max 0' matters: at size 0 the upper bound is negative, and 'choose'+  -- silently swaps inverted bounds instead of failing.+  tailLen <- choose (0, max 0 (min n (size - 1)))+  let totalLen = tailLen + 1+      subsize = size `div` totalLen+      subgen = resize subsize gen+  x <- subgen+  xs <- vectorOf tailLen subgen+  pure (x :| xs)++terminatingMaybe :: Gen a -> Gen (Maybe a)+terminatingMaybe gen = sized $ \size ->+  if size <= 1+    then pure Nothing+    else Just <$> gen
+ library-internal/PostgresqlSyntax/Helpers/Parsers.hs view
@@ -0,0 +1,221 @@+{-# OPTIONS_GHC -Wno-redundant-constraints -Wno-missing-signatures -Wno-dodgy-imports #-}++module PostgresqlSyntax.Helpers.Parsers+  ( module PostgresqlSyntax.Extras.HeadedMegaparsec,+    module PostgresqlSyntax.Helpers.Parsers,+  )+where++import Control.Applicative.Combinators hiding (some)+import qualified Data.HashSet as HashSet+import qualified Data.Text as Text+import HeadedMegaparsec hiding (string)+import PostgresqlSyntax.Extras.HeadedMegaparsec hiding (run)+import PostgresqlSyntax.IsAst hiding (parse, parseWithPosError, toText)+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude hiding (bit, expr, filter, fromList, head, many, option, some, sortBy, tail, try)+import PostgresqlSyntax.Settings (Settings)+import qualified Text.Megaparsec as Megaparsec+import qualified Text.Megaparsec.Char as MegaparsecChar+import qualified TextBuilder++-- $setup+-- >>> import qualified PostgresqlSyntax.Extras.HeadedMegaparsec as HeadedMegaparsec+-- >>> testParser p = either putStr print . HeadedMegaparsec.run p++inSpace :: Parser a -> Parser a+inSpace p = space *> p <* space++commaSeparator :: Parser ()+commaSeparator = space *> char ',' *> endHead *> space++dotSeparator :: Parser ()+dotSeparator = space *> char '.' *> endHead *> space++inBrackets :: Parser a -> Parser a+inBrackets p = char '[' *> space *> p <* endHead <* space <* char ']'++inBracketsCont :: Parser a -> Parser (Parser a)+inBracketsCont p = char '[' *> endHead *> pure (space *> p <* endHead <* space <* char ']')++inParens :: Parser a -> Parser a+inParens p = char '(' *> space *> p <* endHead <* space <* char ')'++inParensCont :: Parser a -> Parser (Parser a)+inParensCont p = char '(' *> endHead *> pure (space *> p <* endHead <* space <* char ')')++inParensWithLabel :: (label -> content -> result) -> Parser label -> Parser content -> Parser result+inParensWithLabel result labelParser contentParser = do+  label <- wrapToHead labelParser+  space+  char '('+  endHead+  space+  content <- contentParser+  space+  char ')'+  pure (result label content)++inParensWithClause :: Parser clause -> Parser content -> Parser content+inParensWithClause = inParensWithLabel (const id)++trueIfPresent :: Parser a -> Parser Bool+trueIfPresent p = option False (True <$ p)++-- |+-- >>> testParser (quotedString '\'') "'abc''d'"+-- "abc'd"+quotedString :: Char -> Parser Text+quotedString q = do+  char q+  endHead+  tail <-+    parse $+      let collectChunks !bdr = do+            chunk <- Megaparsec.takeWhileP Nothing (/= q)+            let bdr' = bdr <> TextBuilder.text chunk+            Megaparsec.try (consumeEscapedQuote bdr') <|> finish bdr'+          consumeEscapedQuote bdr = do+            MegaparsecChar.char q+            MegaparsecChar.char q+            collectChunks (bdr <> TextBuilder.char q)+          finish bdr = do+            MegaparsecChar.char q+            return (TextBuilder.toText bdr)+       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++-- * Keyword-matching infrastructure++--+-- Ported from "PostgresqlSyntax.Parsing". @keywordNameFromSet@\/@keywordNameByPredicate@+-- originally built an @Ident@ directly via its @UnquotedIdent@ constructor;+-- here that constructor is taken as an explicit argument (@wrap@) so this+-- module doesn't need to depend on the (still-monolithic-for-now)+-- 'PostgresqlSyntax.Ast.Ident' type. Callers pass @UnquotedIdent@ for it.++keywordNameFromSet wrap set = keywordNameByPredicate wrap (Predicate.inSet set)++keywordNameByPredicate wrap predicate =+  fmap wrap $+    filter+      (\a -> "Reserved keyword " <> show a <> " used as an identifier. If that's what you intend, you have to wrap it in double quotes.")+      predicate+      anyKeyword++anyKeyword = parse $+  Megaparsec.label "keyword" $+    do+      firstChar <- Megaparsec.satisfy Predicate.firstIdentifierChar+      remainder <- Megaparsec.takeWhileP Nothing Predicate.notFirstIdentifierChar+      return (Text.toLower (Text.cons firstChar remainder))++-- | Expected keyword+--+-- Wraps the head in 'Megaparsec.region' to pin the reported error offset to+-- where this keyword check began. Without this, megaparsec >=9.8's stricter+-- (and correct) '(<|>)' error-merging (fix for+-- <https://github.com/mrkkrp/megaparsec/issues/412>) normalizes any error+-- whose offset lands past the enclosing alternative's start back down to+-- that start, discarding its \"expecting\" set unless the offset already+-- matches exactly. Since every failed keyword branch consumes some+-- identifier text before comparing, its offset always landed past the+-- alternative's start, so wide 'asum'/'choice' chains of 'keyword' lost+-- their combined expected-token sets under 9.8. Pinning the offset up front+-- keeps every branch's offset aligned with the alternative's start, so+-- their expected sets still union correctly.+keyword a = parse $ do+  off <- Megaparsec.getOffset+  Megaparsec.region (Megaparsec.setErrorOffset off) $ do+    firstChar <- Megaparsec.satisfy Predicate.firstIdentifierChar+    remainder <- Megaparsec.takeWhileP Nothing Predicate.notFirstIdentifierChar+    let parsedKeyword = Text.toLower (Text.cons firstChar remainder)+    if a == parsedKeyword then return parsedKeyword else empty++-- |+-- Consume a keyphrase, ignoring case and types of spaces between words.+keyphrase a =+  Text.words a+    & fmap (void . MegaparsecChar.string')+    & intersperse MegaparsecChar.space1+    & sequence_+    & (<* Megaparsec.notFollowedBy (Megaparsec.satisfy Predicate.notFirstIdentifierChar))+    & fmap (const (Text.toUpper a))+    & Megaparsec.label (show a)+    & parse+    & (<* endHead)++-- * Cross-type-family helpers++--+-- Ported from "PostgresqlSyntax.Parsing". Each of these originally called a+-- single concrete node's parser directly (@typename@, @qualOp@,+-- @symbolicExprBinOp@, @fconst@\/@iconst@); here they're generalized over+-- 'IsAst' so any node module can instantiate them for its own node type(s)+-- without this module depending on any of them.++typecastExpr :: (IsAst typename) => Settings -> a -> (a -> typename -> a) -> Parser a+typecastExpr settings prefix constr = do+  space+  string "::"+  endHead+  space+  type' <- parser settings+  return (constr prefix type')++plusedExpr expr = char '+' *> space *> expr++minusedExpr expr = char '-' *> space *> expr++qualOpExpr :: (IsAst qualOp) => Settings -> Parser b -> (qualOp -> b -> a) -> Parser a+qualOpExpr settings expr constr = constr <$> wrapToHead (parser settings) <*> (space *> expr)++symbolicBinOpExpr :: (IsAst symbolicExprBinOp) => Settings -> a -> Parser b -> (a -> symbolicExprBinOp -> b -> c) -> Parser c+symbolicBinOpExpr settings a bParser constr = do+  binOp <- label "binary operator" (space *> wrapToHead (parser settings) <* space)+  b <- bParser+  return (constr a binOp b)++iconstOrFconst :: (IsAst iconst, IsAst fconst) => Settings -> Parser (Either iconst fconst)+iconstOrFconst settings = Right <$> parser settings <|> Left <$> parser settings++-- |+-- Shared by 'PostgresqlSyntax.Ast.FuncApplicationParams' and+-- 'PostgresqlSyntax.Ast.SimpleSelect' (@ALL@\/@DISTINCT@ before a func-arg+-- list, and before a @UNION@\/@INTERSECT@\/@EXCEPT@ right-hand side,+-- respectively).+allOrDistinct :: Parser Bool+allOrDistinct = keyword "all" $> False <|> keyword "distinct" $> True++-- |+-- A ColId-like identifier parser (unreserved keyword ∪ col-name keyword)+-- restricted to exclude the given reserved words — needed wherever a+-- trailing bare word must terminate a construct instead of being consumed+-- as an identifier (e.g. 'PostgresqlSyntax.Ast.SortBy'\'s+-- @USING@\/@ASC@\/@DESC@\/@NULLS@,+-- 'PostgresqlSyntax.Ast.RelationExprOptAlias'\'s alias-terminating+-- keywords). @identParser@ is the identifier type's own plain (unfiltered)+-- parser, tried first, same as plain @ColId@ does.+filteredColIdLike :: (Text -> a) -> Parser a -> [Text] -> Parser a+filteredColIdLike wrap identParser excluded =+  label "identifier" $+    identParser+      <|> keywordNameFromSet wrap (foldr HashSet.delete (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword) excluded)
+ library-internal/PostgresqlSyntax/Helpers/Shrinks.hs view
@@ -0,0 +1,30 @@+-- |+-- Shrink helpers shared by 2+ AST node modules.+module PostgresqlSyntax.Helpers.Shrinks where++import qualified Data.List as List+import qualified Data.Text as Text+import PostgresqlSyntax.Prelude+import qualified Test.QuickCheck as Qc++-- |+-- Shrinks a 'Text' value by shrinking it as a 'String' (dropping\/simplifying+-- characters).+text :: Text -> [Text]+text = fmap Text.pack . Qc.shrink . Text.unpack++-- |+-- Shrinks a 'Text' value, excluding empty results.+nonEmptyText :: Text -> [Text]+nonEmptyText = List.filter (not . Text.null) . text++-- |+-- Shrinks the tail of a 'Text' value, keeping its first character fixed.+-- Useful for text with constraints on the first character (e.g. identifiers),+-- where shrinking it away could produce an invalid result.+textTail :: Text -> [Text]+textTail a =+  case Text.uncons a of+    Nothing -> []+    Just (head, tail) ->+      Text.cons head <$> nonEmptyText tail
+ library-internal/PostgresqlSyntax/Helpers/TextBuilders.hs view
@@ -0,0 +1,35 @@+-- |+-- Rendering helpers shared by 2+ AST node modules.+module PostgresqlSyntax.Helpers.TextBuilders where++import qualified PostgresqlSyntax.Extras.NonEmpty as NonEmpty+import PostgresqlSyntax.Prelude++commaNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder+commaNonEmpty = NonEmpty.intersperseFoldMap ", "++spaceNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder+spaceNonEmpty = NonEmpty.intersperseFoldMap " "++lexemes :: [TextBuilder] -> TextBuilder+lexemes = mconcat . intersperse " "++optLexemes :: [Maybe TextBuilder] -> TextBuilder+optLexemes = lexemes . catMaybes++renderInParens :: TextBuilder -> TextBuilder+renderInParens a = "(" <> a <> ")"++renderInBrackets :: TextBuilder -> TextBuilder+renderInBrackets a = "[" <> a <> "]"++prefixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder+prefixMaybe a = foldMap (flip mappend " " . a)++suffixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder+suffixMaybe a = foldMap (mappend " " . a)++renderAllOrDistinct :: Bool -> TextBuilder+renderAllOrDistinct = \case+  False -> "ALL"+  True -> "DISTINCT"
+ library-internal/PostgresqlSyntax/IsAst.hs view
@@ -0,0 +1,44 @@+module PostgresqlSyntax.IsAst+  ( IsAst (..),+    toText,+    parse,+    parseWithPosError,+    parseWithSourcePosError,+  )+where++import qualified Data.Text as Text+import qualified PostgresqlSyntax.Extras.HeadedMegaparsec as Extras+import PostgresqlSyntax.Prelude+import PostgresqlSyntax.Settings (Settings)+import qualified Text.Megaparsec as Megaparsec+import qualified TextBuilder++class IsAst a where+  toTextBuilder :: Settings -> a -> TextBuilder+  parser :: Settings -> Parser a++-- |+-- Render a value to 'Text' via its 'toTextBuilder' method.+toText :: (IsAst a) => Settings -> a -> Text+toText settings = TextBuilder.toText . toTextBuilder settings++-- |+-- Parse a 'Text' input with the type's 'parser', returning either a+-- pretty-printed error or the parsed value. The parser is chosen by the+-- caller's type inference (via the 'IsAst' constraint), so callers no longer+-- pass an explicit parser argument.+parse :: (IsAst a) => Settings -> Text -> Either Text a+parse settings = first Text.pack . Extras.run (Extras.totally (parser settings))++-- |+-- Like 'parse' but returns the structured error list (each error paired with+-- its byte offset) instead of a single pretty-printed message.+parseWithPosError :: (IsAst a) => Settings -> Text -> Either (NonEmpty (Int, Text)) a+parseWithPosError settings = first (fmap (second Text.pack)) . Extras.runParserWithErrorPos (Extras.totally (parser settings))++-- |+-- Like 'parseWithPosError' but pairs each error with its+-- 'Text.Megaparsec.SourcePos' instead of a raw byte offset.+parseWithSourcePosError :: (IsAst a) => Settings -> Text -> Either (NonEmpty (Megaparsec.SourcePos, Text)) a+parseWithSourcePosError settings = first (fmap (second Text.pack)) . Extras.runParserWithSourcePosError (Extras.totally (parser settings))
+ library-internal/PostgresqlSyntax/KeywordSet.hs view
@@ -0,0 +1,66 @@+module PostgresqlSyntax.KeywordSet where++import Data.HashSet+import PostgresqlSyntax.Prelude hiding (fromList, toList)++{-# NOINLINE keyword #-}+{-+From https://github.com/postgres/postgres/blob/1aac32df89eb19949050f6f27c268122833ad036/src/include/parser/kwlist.h+-}+keyword :: HashSet Text+keyword = fromList ["abort", "absolute", "access", "action", "add", "admin", "after", "aggregate", "all", "also", "alter", "always", "analyse", "analyze", "and", "any", "array", "as", "asc", "assertion", "assignment", "asymmetric", "at", "attach", "attribute", "authorization", "backward", "before", "begin", "between", "bigint", "binary", "bit", "boolean", "both", "by", "cache", "call", "called", "cascade", "cascaded", "case", "cast", "catalog", "chain", "char", "character", "characteristics", "check", "checkpoint", "class", "close", "cluster", "coalesce", "collate", "collation", "column", "columns", "comment", "comments", "commit", "committed", "concurrently", "configuration", "conflict", "connection", "constraint", "constraints", "content", "continue", "conversion", "copy", "cost", "create", "cross", "csv", "cube", "current", "current_catalog", "current_date", "current_role", "current_schema", "current_time", "current_timestamp", "current_user", "cursor", "cycle", "data", "database", "day", "deallocate", "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred", "definer", "delete", "delimiter", "delimiters", "depends", "desc", "detach", "dictionary", "disable", "discard", "distinct", "do", "document", "domain", "double", "drop", "each", "else", "enable", "encoding", "encrypted", "end", "enum", "escape", "event", "except", "exclude", "excluding", "exclusive", "execute", "exists", "explain", "expression", "extension", "external", "extract", "false", "family", "fetch", "filter", "first", "float", "following", "for", "force", "foreign", "forward", "freeze", "from", "full", "function", "functions", "generated", "global", "grant", "granted", "greatest", "group", "grouping", "groups", "handler", "having", "header", "hold", "hour", "identity", "if", "ilike", "immediate", "immutable", "implicit", "import", "in", "include", "including", "increment", "index", "indexes", "inherit", "inherits", "initially", "inline", "inner", "inout", "input", "insensitive", "insert", "instead", "int", "integer", "intersect", "interval", "into", "invoker", "is", "isnull", "isolation", "join", "key", "label", "language", "large", "last", "lateral", "leading", "leakproof", "least", "left", "level", "like", "limit", "listen", "load", "local", "localtime", "localtimestamp", "location", "lock", "locked", "logged", "mapping", "match", "materialized", "maxvalue", "method", "minute", "minvalue", "mode", "month", "move", "name", "names", "national", "natural", "nchar", "new", "next", "nfc", "nfd", "nfkc", "nfkd", "no", "none", "normalize", "normalized", "not", "nothing", "notify", "notnull", "nowait", "null", "nullif", "nulls", "numeric", "object", "of", "off", "offset", "oids", "old", "on", "only", "operator", "option", "options", "or", "order", "ordinality", "others", "out", "outer", "over", "overlaps", "overlay", "overriding", "owned", "owner", "parallel", "parser", "partial", "partition", "passing", "password", "placing", "plans", "policy", "position", "preceding", "precision", "prepare", "prepared", "preserve", "primary", "prior", "privileges", "procedural", "procedure", "procedures", "program", "publication", "quote", "range", "read", "real", "reassign", "recheck", "recursive", "ref", "references", "referencing", "refresh", "reindex", "relative", "release", "rename", "repeatable", "replace", "replica", "reset", "restart", "restrict", "returning", "returns", "revoke", "right", "role", "rollback", "rollup", "routine", "routines", "row", "rows", "rule", "savepoint", "schema", "schemas", "scroll", "search", "second", "security", "select", "sequence", "sequences", "serializable", "server", "session", "session_user", "set", "setof", "sets", "share", "show", "similar", "simple", "skip", "smallint", "snapshot", "some", "sql", "stable", "standalone", "start", "statement", "statistics", "stdin", "stdout", "storage", "stored", "strict", "strip", "subscription", "substring", "support", "symmetric", "sysid", "system", "table", "tables", "tablesample", "tablespace", "temp", "template", "temporary", "text", "then", "ties", "time", "timestamp", "to", "trailing", "transaction", "transform", "treat", "trigger", "trim", "true", "truncate", "trusted", "type", "types", "uescape", "unbounded", "uncommitted", "unencrypted", "union", "unique", "unknown", "unlisten", "unlogged", "until", "update", "user", "using", "vacuum", "valid", "validate", "validator", "value", "values", "varchar", "variadic", "varying", "verbose", "version", "view", "views", "volatile", "when", "where", "whitespace", "window", "with", "within", "without", "work", "wrapper", "write", "xml", "xmlattributes", "xmlconcat", "xmlelement", "xmlexists", "xmlforest", "xmlnamespaces", "xmlparse", "xmlpi", "xmlroot", "xmlserialize", "xmltable", "year", "yes", "zone"]++{-# NOINLINE unreservedKeyword #-}+unreservedKeyword :: HashSet Text+unreservedKeyword = fromList ["abort", "absolute", "access", "action", "add", "admin", "after", "aggregate", "also", "alter", "always", "assertion", "assignment", "at", "attach", "attribute", "backward", "before", "begin", "by", "cache", "call", "called", "cascade", "cascaded", "catalog", "chain", "characteristics", "checkpoint", "class", "close", "cluster", "columns", "comment", "comments", "commit", "committed", "configuration", "conflict", "connection", "constraints", "content", "continue", "conversion", "copy", "cost", "csv", "cube", "current", "cursor", "cycle", "data", "database", "day", "deallocate", "declare", "defaults", "deferred", "definer", "delete", "delimiter", "delimiters", "depends", "detach", "dictionary", "disable", "discard", "document", "domain", "double", "drop", "each", "enable", "encoding", "encrypted", "enum", "escape", "event", "exclude", "excluding", "exclusive", "execute", "explain", "extension", "external", "family", "filter", "first", "following", "force", "forward", "function", "functions", "generated", "global", "granted", "groups", "handler", "header", "hold", "hour", "identity", "if", "immediate", "immutable", "implicit", "import", "include", "including", "increment", "index", "indexes", "inherit", "inherits", "inline", "input", "insensitive", "insert", "instead", "invoker", "isolation", "key", "label", "language", "large", "last", "leakproof", "level", "listen", "load", "local", "location", "lock", "locked", "logged", "mapping", "match", "materialized", "maxvalue", "method", "minute", "minvalue", "mode", "month", "move", "name", "names", "new", "next", "no", "nothing", "notify", "nowait", "nulls", "object", "of", "off", "oids", "old", "operator", "option", "options", "ordinality", "others", "over", "overriding", "owned", "owner", "parallel", "parser", "partial", "partition", "passing", "password", "plans", "policy", "preceding", "prepare", "prepared", "preserve", "prior", "privileges", "procedural", "procedure", "procedures", "program", "publication", "quote", "range", "read", "reassign", "recheck", "recursive", "ref", "referencing", "refresh", "reindex", "relative", "release", "rename", "repeatable", "replace", "replica", "reset", "restart", "restrict", "returns", "revoke", "role", "rollback", "rollup", "routine", "routines", "rows", "rule", "savepoint", "schema", "schemas", "scroll", "search", "second", "security", "sequence", "sequences", "serializable", "server", "session", "set", "sets", "share", "show", "simple", "skip", "snapshot", "sql", "stable", "standalone", "start", "statement", "statistics", "stdin", "stdout", "storage", "stored", "strict", "strip", "subscription", "support", "sysid", "system", "tables", "tablespace", "temp", "template", "temporary", "text", "ties", "transaction", "transform", "trigger", "truncate", "trusted", "type", "types", "unbounded", "uncommitted", "unencrypted", "unknown", "unlisten", "unlogged", "until", "update", "vacuum", "valid", "validate", "validator", "value", "varying", "version", "view", "views", "volatile", "whitespace", "within", "without", "work", "wrapper", "write", "xml", "year", "yes", "zone"]++{-# NOINLINE colNameKeyword #-}+colNameKeyword :: HashSet Text+colNameKeyword = fromList ["between", "bigint", "bit", "boolean", "char", "character", "coalesce", "dec", "decimal", "exists", "extract", "float", "greatest", "grouping", "inout", "int", "integer", "interval", "least", "national", "nchar", "none", "normalize", "nullif", "numeric", "out", "overlay", "position", "precision", "real", "row", "setof", "smallint", "substring", "time", "timestamp", "treat", "trim", "values", "varchar", "xmlattributes", "xmlconcat", "xmlelement", "xmlexists", "xmlforest", "xmlnamespaces", "xmlparse", "xmlpi", "xmlroot", "xmlserialize", "xmltable"]++{-# NOINLINE typeFuncNameKeyword #-}+typeFuncNameKeyword :: HashSet Text+typeFuncNameKeyword = fromList ["authorization", "binary", "collation", "concurrently", "cross", "current_schema", "freeze", "full", "ilike", "inner", "is", "isnull", "join", "left", "like", "natural", "notnull", "outer", "overlaps", "right", "similar", "tablesample", "verbose"]++{-# NOINLINE reservedKeyword #-}+reservedKeyword :: HashSet Text+reservedKeyword = fromList ["all", "analyse", "analyze", "and", "any", "array", "as", "asc", "asymmetric", "both", "case", "cast", "check", "collate", "column", "constraint", "create", "current_catalog", "current_date", "current_role", "current_time", "current_timestamp", "current_user", "default", "deferrable", "desc", "distinct", "do", "else", "end", "except", "false", "fetch", "for", "foreign", "from", "grant", "group", "having", "in", "initially", "intersect", "into", "lateral", "leading", "limit", "localtime", "localtimestamp", "not", "null", "offset", "on", "only", "or", "order", "placing", "primary", "references", "returning", "select", "session_user", "some", "symmetric", "table", "then", "to", "trailing", "true", "union", "unique", "user", "using", "variadic", "when", "where", "window", "with"]++{-# NOINLINE symbolicBinOp #-}+symbolicBinOp :: HashSet Text+symbolicBinOp = fromList ["+", "-", "*", "/", "%", "^", "<", ">", "=", "<=", ">=", "<>", "~~", "~~*", "!~~", "!~~*", "~", "~*", "!~", "!~*"]++{-# NOINLINE lexicalBinOp #-}+lexicalBinOp :: HashSet Text+lexicalBinOp = fromList ["and", "or"]++{-# NOINLINE colId #-}+colId :: HashSet Text+colId = unions [unreservedKeyword, colNameKeyword]++{-+type_function_name:+  | IDENT+  | unreserved_keyword+  | type_func_name_keyword+-}+{-# NOINLINE typeFunctionName #-}+typeFunctionName :: HashSet Text+typeFunctionName = unions [unreservedKeyword, typeFuncNameKeyword]++-- |+-- As per the following comment from the original scanner definition:+--+-- /*+--  * Likewise, if what we have left is two chars, and+--  * those match the tokens ">=", "<=", "=>", "<>" or+--  * "!=", then we must return the appropriate token+--  * rather than the generic Op.+--  */+{-# NOINLINE nonOp #-}+nonOp :: HashSet Text+nonOp = fromList [">=", "<=", "=>", "<>", "!="] <> mathOp++{-# NOINLINE mathOp #-}+mathOp :: HashSet Text+mathOp = fromList ["<>", ">=", "!=", "<=", "+", "-", "*", "/", "%", "^", "<", ">", "="]
+ library-internal/PostgresqlSyntax/Predicate.hs view
@@ -0,0 +1,71 @@+{-# OPTIONS_GHC -Wno-redundant-constraints #-}++module PostgresqlSyntax.Predicate where++import qualified Data.HashSet as HashSet+import qualified PostgresqlSyntax.CharSet as CharSet+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import PostgresqlSyntax.Prelude++-- * Generic++-- |+-- >>> test = oneOf [(==3), (==7), (==3), (==5)]+-- >>> test 1+-- False+--+-- >>> test 3+-- True+--+-- >>> test 5+-- True+oneOf :: [a -> Bool] -> a -> Bool+oneOf = foldr (\a b c -> a c || b c) (const False)++inSet :: (Eq a, Hashable a) => HashSet a -> a -> Bool+inSet = flip HashSet.member++hexDigit :: Char -> Bool+hexDigit = inSet CharSet.hexDigit++{-+ident_start   [A-Za-z\200-\377_]+-}+firstIdentifierChar :: Char -> Bool+firstIdentifierChar x = isAlpha x || x == '_' || x >= '\200' && x <= '\377'++{-+ident_cont    [A-Za-z\200-\377_0-9\$]+-}+notFirstIdentifierChar :: Char -> Bool+notFirstIdentifierChar x = isAlphaNum x || x == '_' || x == '$' || x >= '\200' && x <= '\377'++keyword :: Text -> Bool+keyword = inSet KeywordSet.keyword++unreservedKeyword :: Text -> Bool+unreservedKeyword = inSet KeywordSet.unreservedKeyword++colNameKeyword :: Text -> Bool+colNameKeyword = inSet KeywordSet.colNameKeyword++typeFuncNameKeyword :: Text -> Bool+typeFuncNameKeyword = inSet KeywordSet.typeFuncNameKeyword++reservedKeyword :: Text -> Bool+reservedKeyword = inSet KeywordSet.reservedKeyword++{-# NOINLINE symbolicBinOpChar #-}+symbolicBinOpChar :: Char -> Bool+symbolicBinOpChar = inSet CharSet.symbolicBinOp++-- ** Op chars++opChar :: Char -> Bool+opChar = inSet CharSet.op++prohibitedOpChar :: Char -> Bool+prohibitedOpChar a = a == '+' || a == '-'++prohibitionLiftingOpChar :: Char -> Bool+prohibitionLiftingOpChar = inSet CharSet.prohibitionLiftingOp
+ library-internal/PostgresqlSyntax/Prelude.hs view
@@ -0,0 +1,99 @@+module PostgresqlSyntax.Prelude+  ( module Exports,+    suffixRec,+    extendMany,+    Parser,+  )+where++import Control.Applicative as Exports+import Control.Applicative.Combinators as Exports (option)+import Control.Arrow as Exports hiding (first, second)+import Control.Category as Exports+import Control.Concurrent as Exports+import Control.Exception as Exports+import Control.Monad as Exports hiding (fail, forM, forM_, mapM, mapM_, msum, sequence, sequence_)+import Control.Monad.Fail as Exports+import Control.Monad.Fix as Exports hiding (fix)+import Control.Monad.IO.Class as Exports+import Control.Monad.ST as Exports+import Data.Bifunctor as Exports+import Data.Bits as Exports+import Data.Bool as Exports+import Data.ByteString as Exports (ByteString)+import Data.CaseInsensitive as Exports (CI, FoldCase)+import Data.Char as Exports+import Data.Coerce as Exports+import Data.Complex as Exports+import Data.Data as Exports+import Data.Dynamic as Exports+import Data.Either as Exports+import Data.Fixed as Exports+import Data.Foldable as Exports+import Data.Function as Exports hiding (id, (.))+import Data.Functor as Exports hiding (unzip)+import Data.Functor.Identity as Exports+import Data.HashMap.Strict as Exports (HashMap)+import Data.HashSet as Exports (HashSet)+import Data.Hashable as Exports (Hashable)+import Data.IORef as Exports+import Data.Int as Exports+import Data.Ix as Exports+import Data.List as Exports hiding (all, and, any, concat, concatMap, elem, find, foldl, foldl', foldl1, foldr, foldr1, isSubsequenceOf, mapAccumL, mapAccumR, maximum, maximumBy, minimum, minimumBy, notElem, or, product, sortOn, sum, uncons, unsnoc)+import Data.List.NonEmpty as Exports (NonEmpty (..))+import Data.Maybe as Exports+import Data.Monoid as Exports hiding (First (..), Last (..), (<>))+import Data.Ord as Exports+import Data.Proxy as Exports+import Data.Ratio as Exports+import Data.STRef as Exports+import Data.Semigroup as Exports (Semigroup (..), stimes, stimesIdempotent, stimesIdempotentMonoid, stimesMonoid)+import Data.String as Exports+import Data.Text as Exports (Text)+import Data.Traversable as Exports+import Data.Tuple as Exports+import Data.Unique as Exports+import Data.Version as Exports+import Data.Void as Exports+import Data.Word as Exports+import Debug.Trace as Exports+import Foreign.ForeignPtr as Exports+import Foreign.Ptr as Exports+import Foreign.StablePtr as Exports+import Foreign.Storable as Exports hiding (alignment, sizeOf)+import GHC.Conc as Exports hiding (orElse, threadWaitRead, threadWaitReadSTM, threadWaitWrite, threadWaitWriteSTM, withMVar)+import GHC.Exts as Exports (IsList (Item, fromList), groupWith, inline, lazy, sortWith)+import GHC.Generics as Exports (Generic, Generic1)+import GHC.IO.Exception as Exports+import qualified HeadedMegaparsec+import Numeric as Exports+import System.Environment as Exports+import System.Exit as Exports+import System.IO as Exports+import System.IO.Error as Exports+import System.IO.Unsafe as Exports+import System.Mem as Exports+import System.Mem.StableName as Exports+import System.Timeout as Exports+import Test.QuickCheck as Exports (Arbitrary (..), Gen, choose, elements, listOf, oneof, sized, vectorOf)+import Text.Printf as Exports (hPrintf, printf)+import Text.Read as Exports (Read (..), readEither, readMaybe)+import TextBuilder as Exports (TextBuilder)+import Unsafe.Coerce as Exports+import Prelude as Exports hiding (all, and, any, concat, concatMap, elem, fail, foldl, foldl1, foldr, foldr1, id, mapM, mapM_, maximum, minimum, notElem, or, product, sequence, sequence_, sum, (.))++-- |+-- Compose a monad, which attempts to extend a value, based on the following input.+-- It does so recursively until the suffix alternative fails.+suffixRec :: (MonadPlus m) => m a -> (a -> m a) -> m a+suffixRec base suffix = base >>= extendMany suffix++extendMany :: (MonadPlus m) => (a -> m a) -> a -> m a+extendMany attempt = loop+  where+    loop !state =+      optional (attempt state) >>= \case+        Nothing -> pure state+        Just newState -> loop newState++type Parser = HeadedMegaparsec.HeadedParsec Void Text
+ library-internal/PostgresqlSyntax/Settings.hs view
@@ -0,0 +1,44 @@+-- |+-- Parse\/render options for the 'PostgresqlSyntax.IsAst' machinery.+--+-- The type is abstract: build a 'Settings' value with 'nullabilityMarkers' and+-- combine values with their 'Semigroup'\/'Monoid' instances ('mempty' is+-- faithful, standard Postgres). Because no constructor or field selector is+-- exported, a resolved configuration indirection can be introduced later+-- without a breaking change.+module PostgresqlSyntax.Settings+  ( Settings,+    nullabilityMarkers,+    resolveNullabilityMarkers,+  )+where++import PostgresqlSyntax.Prelude++-- |+-- \@Settings {optNullabilityMarkers = Nothing}\@ everywhere means standard+-- Postgres. The only knob today is whether the 'PostgresqlSyntax.Ast.Typename'+-- @?@ nullability markers are recognized.+data Settings = Settings {optNullabilityMarkers :: Maybe Bool}+  deriving (Show, Eq)++-- | Per option the right operand wins; an unset ('Nothing') option falls back+-- to the left operand's value.+instance Semigroup Settings where+  a <> b = Settings {optNullabilityMarkers = optNullabilityMarkers b <|> optNullabilityMarkers a}++instance Monoid Settings where+  mempty = Settings Nothing++-- |+-- The only public constructor: opt into (or out of) the+-- 'PostgresqlSyntax.Ast.Typename' @?@ nullability markers.+nullabilityMarkers :: Bool -> Settings+nullabilityMarkers = Settings . Just++-- |+-- Resolve the nullability-marker option to its effective value, defaulting to+-- @False@ (standard Postgres). Internal — used at parse\/render sites, not+-- re-exported from the "PostgresqlSyntax" facade.+resolveNullabilityMarkers :: Settings -> Bool+resolveNullabilityMarkers = fromMaybe False . optNullabilityMarkers
+ library-internal/PostgresqlSyntax/Validation.hs view
@@ -0,0 +1,54 @@+module PostgresqlSyntax.Validation where++import qualified Data.Text as Text+import qualified PostgresqlSyntax.KeywordSet as KeywordSet+import qualified PostgresqlSyntax.Predicate as Predicate+import PostgresqlSyntax.Prelude++{-+The operator name is a sequence of up to NAMEDATALEN-1 (63 by default)+characters from the following list:+++ - * / < > = ~ ! @ # % ^ & | ` ?++There are a few restrictions on your choice of name:+-- and /* cannot appear anywhere in an operator name,+since they will be taken as the start of a comment.++A multicharacter operator name cannot end in + or -,+unless the name also contains at least one of these characters:++~ ! @ # % ^ & | ` ?++For example, @- is an allowed operator name, but *- is not.+This restriction allows PostgreSQL to parse SQL-compliant+commands without requiring spaces between tokens.+The use of => as an operator name is deprecated.+It may be disallowed altogether in a future release.++The operator != is mapped to <> on input,+so these two names are always equivalent.+-}+op :: Text -> Maybe Text+op a =+  if Text.null a+    then Just ("Operator is empty")+    else+      if Text.any (not . Predicate.opChar) a+        then Just ("Operator contains a char that's not a valid operator char: " <> a)+        else+          if Text.isInfixOf "--" a+            then Just ("Operator contains a prohibited \"--\" sequence: " <> a)+            else+              if Text.isInfixOf "/*" a+                then Just ("Operator contains a prohibited \"/*\" sequence: " <> a)+                else+                  if Predicate.inSet KeywordSet.nonOp a+                    then Just ("Operator is not generic: " <> a)+                    else+                      if Text.find Predicate.prohibitionLiftingOpChar a & isJust+                        then Nothing+                        else+                          if Predicate.prohibitedOpChar (Text.last a)+                            then Just ("Operator ends with a prohibited char: " <> a)+                            else Nothing
+ library/PostgresqlSyntax.hs view
@@ -0,0 +1,32 @@+-- |+-- Parse Postgres SQL fragments into an AST and render that AST back to text.+--+-- Pick the 'PostgresqlSyntax.Ast' node type that corresponds to the syntax+-- you want to parse (e.g. 'PostgresqlSyntax.Ast.AExpr' for an expression),+-- then use 'parse' (or one of its error-detail variants) to get a value of+-- that type. Use 'toText' to go the other way and render an AST value back+-- into Postgres SQL syntax.+--+-- 'Settings' (built via 'nullabilityMarkers' and combined with+-- 'Semigroup'\/'Monoid') control optional parsing\/rendering behavior; pass+-- 'mempty' for standard Postgres syntax.+module PostgresqlSyntax+  ( -- * Parsing and rendering+    IsAst.IsAst (..),+    IsAst.toText,+    IsAst.parse,+    IsAst.parseWithPosError,+    IsAst.parseWithSourcePosError,++    -- * Settings+    Settings.Settings,+    Settings.nullabilityMarkers,++    -- * AST+    module PostgresqlSyntax.Ast,+  )+where++import PostgresqlSyntax.Ast+import qualified PostgresqlSyntax.IsAst as IsAst+import qualified PostgresqlSyntax.Settings as Settings
− library/PostgresqlSyntax/Ast.hs
@@ -1,2340 +0,0 @@--- |--- Names for nodes mostly resemble the according definitions in the @gram.y@--- original Postgres parser file, except for the cases where we can optimize on that.------ For reasoning see the docs of the parsing module of this project.-module PostgresqlSyntax.Ast where--import PostgresqlSyntax.Prelude---- * Statement---- |--- ==== References--- @--- PreparableStmt:---   |  SelectStmt---   |  InsertStmt---   |  UpdateStmt---   |  DeleteStmt---   |  CallStmt--- @-data PreparableStmt-  = SelectPreparableStmt SelectStmt-  | InsertPreparableStmt InsertStmt-  | UpdatePreparableStmt UpdateStmt-  | DeletePreparableStmt DeleteStmt-  | CallPreparableStmt CallStmt-  deriving (Show, Generic, Eq, Ord, Data)---- * Call--newtype CallStmt-  = CallStmt FuncApplication-  deriving (Show, Generic, Eq, Ord, Data)---- * Insert---- |--- ==== References--- @--- InsertStmt:---   | opt_with_clause INSERT INTO insert_target insert_rest---       opt_on_conflict returning_clause--- @-data InsertStmt = InsertStmt (Maybe WithClause) InsertTarget InsertRest (Maybe OnConflict) (Maybe ReturningClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- insert_target:---   | qualified_name---   | qualified_name AS ColId--- @-data InsertTarget = InsertTarget QualifiedName (Maybe ColId)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- insert_rest:---   | SelectStmt---   | OVERRIDING override_kind VALUE_P SelectStmt---   | '(' insert_column_list ')' SelectStmt---   | '(' insert_column_list ')' OVERRIDING override_kind VALUE_P SelectStmt---   | DEFAULT VALUES--- @-data InsertRest-  = SelectInsertRest (Maybe InsertColumnList) (Maybe OverrideKind) SelectStmt-  | DefaultValuesInsertRest-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- override_kind:---   | USER---   | SYSTEM_P--- @-data OverrideKind = UserOverrideKind | SystemOverrideKind-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)---- |--- ==== References--- @--- insert_column_list:---   | insert_column_item---   | insert_column_list ',' insert_column_item--- @-type InsertColumnList = NonEmpty InsertColumnItem---- |--- ==== References--- @--- insert_column_item:---   | ColId opt_indirection--- @-data InsertColumnItem = InsertColumnItem ColId (Maybe Indirection)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_on_conflict:---   | ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list where_clause---   | ON CONFLICT opt_conf_expr DO NOTHING---   | EMPTY--- @-data OnConflict = OnConflict (Maybe ConfExpr) OnConflictDo-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_on_conflict:---   | ON CONFLICT opt_conf_expr DO UPDATE SET set_clause_list where_clause---   | ON CONFLICT opt_conf_expr DO NOTHING---   | EMPTY--- @-data OnConflictDo-  = UpdateOnConflictDo SetClauseList (Maybe WhereClause)-  | NothingOnConflictDo-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_conf_expr:---   | '(' index_params ')' where_clause---   | ON CONSTRAINT name---   | EMPTY--- @-data ConfExpr-  = WhereConfExpr IndexParams (Maybe WhereClause)-  | ConstraintConfExpr Name-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- returning_clause:---   | RETURNING target_list---   | EMPTY--- @-type ReturningClause = TargetList---- * Update---- |--- ==== References--- @--- UpdateStmt:---   | opt_with_clause UPDATE relation_expr_opt_alias---       SET set_clause_list---       from_clause---       where_or_current_clause---       returning_clause--- @-data UpdateStmt = UpdateStmt (Maybe WithClause) RelationExprOptAlias SetClauseList (Maybe FromClause) (Maybe WhereOrCurrentClause) (Maybe ReturningClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- set_clause_list:---   | set_clause---   | set_clause_list ',' set_clause--- @-type SetClauseList = NonEmpty SetClause---- |--- ==== References--- @--- set_clause:---   | set_target '=' a_expr---   | '(' set_target_list ')' '=' a_expr--- @-data SetClause-  = TargetSetClause SetTarget AExpr-  | TargetListSetClause SetTargetList AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- set_target:---   | ColId opt_indirection--- @-data SetTarget = SetTarget ColId (Maybe Indirection)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- set_target_list:---   | set_target---   | set_target_list ',' set_target--- @-type SetTargetList = NonEmpty SetTarget---- * Delete---- |--- ==== References--- @--- DeleteStmt:---   | opt_with_clause DELETE_P FROM relation_expr_opt_alias---       using_clause where_or_current_clause returning_clause--- @-data DeleteStmt = DeleteStmt (Maybe WithClause) RelationExprOptAlias (Maybe UsingClause) (Maybe WhereOrCurrentClause) (Maybe ReturningClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- using_clause:---   | USING from_list---   | EMPTY--- @-type UsingClause = FromList---- * Select---- |--- ==== References--- @--- SelectStmt:---   |  select_no_parens---   |  select_with_parens--- @-type SelectStmt = Either SelectNoParens SelectWithParens---- |--- ==== References--- @--- select_with_parens:---   |  '(' select_no_parens ')'---   |  '(' select_with_parens ')'--- @-data SelectWithParens-  = NoParensSelectWithParens SelectNoParens-  | WithParensSelectWithParens SelectWithParens-  deriving (Show, Generic, Eq, Ord, Data)---- |--- Covers the following cases:------ @--- select_no_parens:---   |  simple_select---   |  select_clause sort_clause---   |  select_clause opt_sort_clause for_locking_clause opt_select_limit---   |  select_clause opt_sort_clause select_limit opt_for_locking_clause---   |  with_clause select_clause---   |  with_clause select_clause sort_clause---   |  with_clause select_clause opt_sort_clause for_locking_clause opt_select_limit---   |  with_clause select_clause opt_sort_clause select_limit opt_for_locking_clause--- @-data SelectNoParens-  = SelectNoParens (Maybe WithClause) SelectClause (Maybe SortClause) (Maybe SelectLimit) (Maybe ForLockingClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- @--- select_clause:---   |  simple_select---   |  select_with_parens--- @-type SelectClause = Either SimpleSelect SelectWithParens---- |--- ==== References--- @--- simple_select:---   |  SELECT opt_all_clause opt_target_list---       into_clause from_clause where_clause---       group_clause having_clause window_clause---   |  SELECT distinct_clause target_list---       into_clause from_clause where_clause---       group_clause having_clause window_clause---   |  values_clause---   |  TABLE relation_expr---   |  select_clause UNION all_or_distinct select_clause---   |  select_clause INTERSECT all_or_distinct select_clause---   |  select_clause EXCEPT all_or_distinct select_clause--- @-data SimpleSelect-  = NormalSimpleSelect (Maybe Targeting) (Maybe IntoClause) (Maybe FromClause) (Maybe WhereClause) (Maybe GroupClause) (Maybe HavingClause) (Maybe WindowClause)-  | ValuesSimpleSelect ValuesClause-  | TableSimpleSelect RelationExpr-  | BinSimpleSelect SelectBinOp SelectClause (Maybe Bool) SelectClause-  deriving (Show, Generic, Eq, Ord, Data)---- |--- Covers these parts of spec:------ ==== References--- @--- simple_select:---   |  SELECT opt_all_clause opt_target_list---       into_clause from_clause where_clause---       group_clause having_clause window_clause---   |  SELECT distinct_clause target_list---       into_clause from_clause where_clause---       group_clause having_clause window_clause------ distinct_clause:---   |  DISTINCT---   |  DISTINCT ON '(' expr_list ')'--- @-data Targeting-  = NormalTargeting TargetList-  | AllTargeting (Maybe TargetList)-  | DistinctTargeting (Maybe ExprList) TargetList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- target_list:---   | target_el---   | target_list ',' target_el--- @-type TargetList = NonEmpty TargetEl---- |--- ==== References--- @--- target_el:---   |  a_expr AS ColLabel---   |  a_expr IDENT---   |  a_expr---   |  '*'--- @-data TargetEl-  = AliasedExprTargetEl AExpr Ident-  | ImplicitlyAliasedExprTargetEl AExpr Ident-  | ExprTargetEl AExpr-  | AsteriskTargetEl-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @---   |  select_clause UNION all_or_distinct select_clause---   |  select_clause INTERSECT all_or_distinct select_clause---   |  select_clause EXCEPT all_or_distinct select_clause--- @-data SelectBinOp = UnionSelectBinOp | IntersectSelectBinOp | ExceptSelectBinOp-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- with_clause:---   |  WITH cte_list---   |  WITH_LA cte_list---   |  WITH RECURSIVE cte_list--- @-data WithClause = WithClause Bool (NonEmpty CommonTableExpr)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- common_table_expr:---   |  name opt_name_list AS opt_materialized '(' PreparableStmt ')'--- opt_materialized:---   | MATERIALIZED---   | NOT MATERIALIZED---   | EMPTY--- @-data CommonTableExpr = CommonTableExpr Ident (Maybe (NonEmpty Ident)) (Maybe Bool) PreparableStmt-  deriving (Show, Generic, Eq, Ord, Data)--type IntoClause = OptTempTableName---- |--- ==== References--- @--- OptTempTableName:---   |  TEMPORARY opt_table qualified_name---   |  TEMP opt_table qualified_name---   |  LOCAL TEMPORARY opt_table qualified_name---   |  LOCAL TEMP opt_table qualified_name---   |  GLOBAL TEMPORARY opt_table qualified_name---   |  GLOBAL TEMP opt_table qualified_name---   |  UNLOGGED opt_table qualified_name---   |  TABLE qualified_name---   |  qualified_name--- @-data OptTempTableName-  = TemporaryOptTempTableName Bool QualifiedName-  | TempOptTempTableName Bool QualifiedName-  | LocalTemporaryOptTempTableName Bool QualifiedName-  | LocalTempOptTempTableName Bool QualifiedName-  | GlobalTemporaryOptTempTableName Bool QualifiedName-  | GlobalTempOptTempTableName Bool QualifiedName-  | UnloggedOptTempTableName Bool QualifiedName-  | TableOptTempTableName QualifiedName-  | QualifedOptTempTableName QualifiedName-  deriving (Show, Generic, Eq, Ord, Data)--type FromClause = NonEmpty TableRef--type GroupClause = NonEmpty GroupByItem---- |--- ==== References--- @--- group_by_item:---   |  a_expr---   |  empty_grouping_set---   |  cube_clause---   |  rollup_clause---   |  grouping_sets_clause--- empty_grouping_set:---   |  '(' ')'--- rollup_clause:---   |  ROLLUP '(' expr_list ')'--- cube_clause:---   |  CUBE '(' expr_list ')'--- grouping_sets_clause:---   |  GROUPING SETS '(' group_by_list ')'--- @-data GroupByItem-  = ExprGroupByItem AExpr-  | EmptyGroupingSetGroupByItem-  | RollupGroupByItem ExprList-  | CubeGroupByItem ExprList-  | GroupingSetsGroupByItem (NonEmpty GroupByItem)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- @--- having_clause:---   |  HAVING a_expr---   |  EMPTY--- @-type HavingClause = AExpr---- |--- @--- window_clause:---   |  WINDOW window_definition_list---   |  EMPTY------ window_definition_list:---   |  window_definition---   |  window_definition_list ',' window_definition--- @-type WindowClause = NonEmpty WindowDefinition---- |--- @--- window_definition:---   |  ColId AS window_specification--- @-data WindowDefinition = WindowDefinition Ident WindowSpecification-  deriving (Show, Generic, Eq, Ord, Data)---- |--- @--- window_specification:---   |  '(' opt_existing_window_name opt_partition_clause---             opt_sort_clause opt_frame_clause ')'------ opt_existing_window_name:---   |  ColId---   |  EMPTY------ opt_partition_clause:---   |  PARTITION BY expr_list---   |  EMPTY--- @-data WindowSpecification = WindowSpecification (Maybe ExistingWindowName) (Maybe PartitionClause) (Maybe SortClause) (Maybe FrameClause)-  deriving (Show, Generic, Eq, Ord, Data)--type ExistingWindowName = ColId--type PartitionClause = ExprList---- |--- ==== References--- @--- opt_frame_clause:---   |  RANGE frame_extent opt_window_exclusion_clause---   |  ROWS frame_extent opt_window_exclusion_clause---   |  GROUPS frame_extent opt_window_exclusion_clause---   |  EMPTY--- @-data FrameClause = FrameClause FrameClauseMode FrameExtent (Maybe WindowExclusionClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_frame_clause:---   |  RANGE frame_extent opt_window_exclusion_clause---   |  ROWS frame_extent opt_window_exclusion_clause---   |  GROUPS frame_extent opt_window_exclusion_clause---   |  EMPTY--- @-data FrameClauseMode = RangeFrameClauseMode | RowsFrameClauseMode | GroupsFrameClauseMode-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- frame_extent:---   |  frame_bound---   |  BETWEEN frame_bound AND frame_bound--- @-data FrameExtent = SingularFrameExtent FrameBound | BetweenFrameExtent FrameBound FrameBound-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- frame_bound:---   |  UNBOUNDED PRECEDING---   |  UNBOUNDED FOLLOWING---   |  CURRENT_P ROW---   |  a_expr PRECEDING---   |  a_expr FOLLOWING--- @-data FrameBound-  = UnboundedPrecedingFrameBound-  | UnboundedFollowingFrameBound-  | CurrentRowFrameBound-  | PrecedingFrameBound AExpr-  | FollowingFrameBound AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_window_exclusion_clause:---   |  EXCLUDE CURRENT_P ROW---   |  EXCLUDE GROUP_P---   |  EXCLUDE TIES---   |  EXCLUDE NO OTHERS---   |  EMPTY--- @-data WindowExclusionClause-  = CurrentRowWindowExclusionClause-  | GroupWindowExclusionClause-  | TiesWindowExclusionClause-  | NoOthersWindowExclusionClause-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- values_clause:---   |  VALUES '(' expr_list ')'---   |  values_clause ',' '(' expr_list ')'--- @-type ValuesClause = NonEmpty ExprList---- |------ sort_clause:---   |  ORDER BY sortby_list------ sortby_list:---   |  sortby---   |  sortby_list ',' sortby-type SortClause = NonEmpty SortBy---- |--- ==== References--- @--- sortby:---   |  a_expr USING qual_all_Op opt_nulls_order---   |  a_expr opt_asc_desc opt_nulls_order--- @-data SortBy-  = UsingSortBy AExpr QualAllOp (Maybe NullsOrder)-  | AscDescSortBy AExpr (Maybe AscDesc) (Maybe NullsOrder)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- select_limit:---   | limit_clause offset_clause---   | offset_clause limit_clause---   | limit_clause---   | offset_clause--- @-data SelectLimit-  = LimitOffsetSelectLimit LimitClause OffsetClause-  | OffsetLimitSelectLimit OffsetClause LimitClause-  | LimitSelectLimit LimitClause-  | OffsetSelectLimit OffsetClause-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- limit_clause:---   | LIMIT select_limit_value---   | LIMIT select_limit_value ',' select_offset_value---   | FETCH first_or_next select_fetch_first_value row_or_rows ONLY---   | FETCH first_or_next row_or_rows ONLY--- select_offset_value:---   | a_expr--- first_or_next:---   | FIRST_P---   | NEXT--- row_or_rows:---   | ROW---   | ROWS--- @-data LimitClause-  = LimitLimitClause SelectLimitValue (Maybe AExpr)-  | FetchOnlyLimitClause Bool (Maybe SelectFetchFirstValue) Bool-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- select_fetch_first_value:---   | c_expr---   | '+' I_or_F_const---   | '-' I_or_F_const--- @-data SelectFetchFirstValue-  = ExprSelectFetchFirstValue CExpr-  | NumSelectFetchFirstValue Bool (Either Int64 Double)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- select_limit_value:---   | a_expr---   | ALL--- @-data SelectLimitValue-  = ExprSelectLimitValue AExpr-  | AllSelectLimitValue-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- offset_clause:---   | OFFSET select_offset_value---   | OFFSET select_fetch_first_value row_or_rows--- select_offset_value:---   | a_expr--- row_or_rows:---   | ROW---   | ROWS--- @-data OffsetClause-  = ExprOffsetClause AExpr-  | FetchFirstOffsetClause SelectFetchFirstValue Bool-  deriving (Show, Generic, Eq, Ord, Data)---- * For Locking---- |--- ==== References--- @--- for_locking_clause:---   | for_locking_items---   | FOR READ ONLY--- for_locking_items:---   | for_locking_item---   | for_locking_items for_locking_item--- @-data ForLockingClause-  = ItemsForLockingClause (NonEmpty ForLockingItem)-  | ReadOnlyForLockingClause-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- for_locking_item:---   | for_locking_strength locked_rels_list opt_nowait_or_skip--- locked_rels_list:---   | OF qualified_name_list---   | EMPTY--- opt_nowait_or_skip:---   | NOWAIT---   | SKIP LOCKED---   | EMPTY--- @-data ForLockingItem = ForLockingItem ForLockingStrength (Maybe (NonEmpty QualifiedName)) (Maybe Bool)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- for_locking_strength:---   | FOR UPDATE---   | FOR NO KEY UPDATE---   | FOR SHARE---   | FOR KEY SHARE--- @-data ForLockingStrength-  = UpdateForLockingStrength-  | NoKeyUpdateForLockingStrength-  | ShareForLockingStrength-  | KeyForLockingStrength-  deriving (Show, Generic, Eq, Ord, Data)---- * Table references and joining---- |--- ==== References--- @--- from_list:---   | table_ref---   | from_list ',' table_ref--- @-type FromList = NonEmpty TableRef---- |--- ==== References--- @--- | relation_expr opt_alias_clause--- | relation_expr opt_alias_clause tablesample_clause--- | func_table func_alias_clause--- | LATERAL_P func_table func_alias_clause--- | xmltable opt_alias_clause--- | LATERAL_P xmltable opt_alias_clause--- | select_with_parens opt_alias_clause--- | LATERAL_P select_with_parens opt_alias_clause--- | joined_table--- | '(' joined_table ')' alias_clause------ TODO: Add xmltable--- @-data TableRef-  = -- |-    -- @-    --    | relation_expr opt_alias_clause-    --    | relation_expr opt_alias_clause tablesample_clause-    -- @-    RelationExprTableRef RelationExpr (Maybe AliasClause) (Maybe TablesampleClause)-  | -- |-    -- @-    --    | func_table func_alias_clause-    --    | LATERAL_P func_table func_alias_clause-    -- @-    FuncTableRef Bool FuncTable (Maybe FuncAliasClause)-  | -- |-    -- @-    --    | select_with_parens opt_alias_clause-    --    | LATERAL_P select_with_parens opt_alias_clause-    -- @-    SelectTableRef Bool SelectWithParens (Maybe AliasClause)-  | -- |-    -- @-    --    | joined_table-    --    | '(' joined_table ')' alias_clause-    -- @-    JoinTableRef JoinedTable (Maybe AliasClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- | qualified_name--- | qualified_name '*'--- | ONLY qualified_name--- | ONLY '(' qualified_name ')'--- @-data RelationExpr-  = SimpleRelationExpr-      -- | Name.-      QualifiedName-      -- | Is asterisk present?-      Bool-  | OnlyRelationExpr-      -- | Name.-      QualifiedName-      -- | Are parentheses present?-      Bool-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- relation_expr_opt_alias:---   | relation_expr---   | relation_expr ColId---   | relation_expr AS ColId--- @-data RelationExprOptAlias = RelationExprOptAlias RelationExpr (Maybe (Bool, ColId))-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- tablesample_clause:---   | TABLESAMPLE func_name '(' expr_list ')' opt_repeatable_clause--- @-data TablesampleClause = TablesampleClause FuncName ExprList (Maybe RepeatableClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_repeatable_clause:---   | REPEATABLE '(' a_expr ')'---   | EMPTY--- @-type RepeatableClause = AExpr---- |--- ==== References--- @--- func_table:---   | func_expr_windowless opt_ordinality---   | ROWS FROM '(' rowsfrom_list ')' opt_ordinality--- @-data FuncTable-  = FuncExprFuncTable FuncExprWindowless OptOrdinality-  | RowsFromFuncTable RowsfromList OptOrdinality-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- rowsfrom_item:---   | func_expr_windowless opt_col_def_list--- @-data RowsfromItem = RowsfromItem FuncExprWindowless (Maybe ColDefList)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- rowsfrom_list:---   | rowsfrom_item---   | rowsfrom_list ',' rowsfrom_item--- @-type RowsfromList = NonEmpty RowsfromItem---- |--- ==== References--- @--- opt_col_def_list:---   | AS '(' TableFuncElementList ')'---   | EMPTY--- @-type ColDefList = TableFuncElementList---- |--- ==== References--- @--- opt_ordinality:---   | WITH_LA ORDINALITY---   | EMPTY--- @-type OptOrdinality = Bool---- |--- ==== References--- @--- TableFuncElementList:---   | TableFuncElement---   | TableFuncElementList ',' TableFuncElement--- @-type TableFuncElementList = NonEmpty TableFuncElement---- |--- ==== References--- @--- TableFuncElement:---   | ColId Typename opt_collate_clause--- @-data TableFuncElement = TableFuncElement ColId Typename (Maybe CollateClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_collate_clause:---   | COLLATE any_name---   | EMPTY--- @-type CollateClause = AnyName---- |--- ==== References--- @--- alias_clause:---   |  AS ColId '(' name_list ')'---   |  AS ColId---   |  ColId '(' name_list ')'---   |  ColId--- @-data AliasClause = AliasClause Bool ColId (Maybe NameList)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_alias_clause:---   | alias_clause---   | AS '(' TableFuncElementList ')'---   | AS ColId '(' TableFuncElementList ')'---   | ColId '(' TableFuncElementList ')'---   | EMPTY--- @-data FuncAliasClause-  = AliasFuncAliasClause AliasClause-  | AsFuncAliasClause TableFuncElementList-  | AsColIdFuncAliasClause ColId TableFuncElementList-  | ColIdFuncAliasClause ColId TableFuncElementList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- | '(' joined_table ')'--- | table_ref CROSS JOIN table_ref--- | table_ref join_type JOIN table_ref join_qual--- | table_ref JOIN table_ref join_qual--- | table_ref NATURAL join_type JOIN table_ref--- | table_ref NATURAL JOIN table_ref------ The options are covered by the `JoinMeth` type.--- @-data JoinedTable-  = InParensJoinedTable JoinedTable-  | MethJoinedTable JoinMeth TableRef TableRef-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- | table_ref CROSS JOIN table_ref--- | table_ref join_type JOIN table_ref join_qual--- | table_ref JOIN table_ref join_qual--- | table_ref NATURAL join_type JOIN table_ref--- | table_ref NATURAL JOIN table_ref--- @-data JoinMeth-  = CrossJoinMeth-  | QualJoinMeth (Maybe JoinType) JoinQual-  | NaturalJoinMeth (Maybe JoinType)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- | FULL join_outer--- | LEFT join_outer--- | RIGHT join_outer--- | INNER_P--- @-data JoinType-  = FullJoinType Bool-  | LeftJoinType Bool-  | RightJoinType Bool-  | InnerJoinType-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- join_qual:---   |  USING '(' name_list ')'---   |  ON a_expr--- @-data JoinQual-  = UsingJoinQual (NonEmpty Ident)-  | OnJoinQual AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- * Where--type WhereClause = AExpr---- |--- ==== References--- @--- | WHERE a_expr--- | WHERE CURRENT_P OF cursor_name--- | /*EMPTY*/--- @-data WhereOrCurrentClause-  = ExprWhereOrCurrentClause AExpr-  | CursorWhereOrCurrentClause CursorName-  deriving (Show, Generic, Eq, Ord, Data)---- * Expression--type ExprList = NonEmpty AExpr---- |--- ==== References--- @--- a_expr:---   | c_expr---   | a_expr TYPECAST Typename---   | a_expr COLLATE any_name---   | a_expr AT TIME ZONE a_expr---   | '+' a_expr---   | '-' a_expr---   | a_expr '+' a_expr---   | a_expr '-' a_expr---   | a_expr '*' a_expr---   | a_expr '/' a_expr---   | a_expr '%' a_expr---   | a_expr '^' a_expr---   | a_expr '<' a_expr---   | a_expr '>' a_expr---   | a_expr '=' a_expr---   | a_expr LESS_EQUALS a_expr---   | a_expr GREATER_EQUALS a_expr---   | a_expr NOT_EQUALS a_expr---   | a_expr qual_Op a_expr---   | qual_Op a_expr---   | a_expr qual_Op---   | a_expr AND a_expr---   | a_expr OR a_expr---   | NOT a_expr---   | NOT_LA a_expr---   | a_expr LIKE a_expr---   | a_expr LIKE a_expr ESCAPE a_expr---   | a_expr NOT_LA LIKE a_expr---   | a_expr NOT_LA LIKE a_expr ESCAPE a_expr---   | a_expr ILIKE a_expr---   | a_expr ILIKE a_expr ESCAPE a_expr---   | a_expr NOT_LA ILIKE a_expr---   | a_expr NOT_LA ILIKE a_expr ESCAPE a_expr---   | a_expr SIMILAR TO a_expr---   | a_expr SIMILAR TO a_expr ESCAPE a_expr---   | a_expr NOT_LA SIMILAR TO a_expr---   | a_expr NOT_LA SIMILAR TO a_expr ESCAPE a_expr---   | a_expr IS NULL_P---   | a_expr ISNULL---   | a_expr IS NOT NULL_P---   | a_expr NOTNULL---   | row OVERLAPS row---   | a_expr IS TRUE_P---   | a_expr IS NOT TRUE_P---   | a_expr IS FALSE_P---   | a_expr IS NOT FALSE_P---   | a_expr IS UNKNOWN---   | a_expr IS NOT UNKNOWN---   | a_expr IS DISTINCT FROM a_expr---   | a_expr IS NOT DISTINCT FROM a_expr---   | a_expr IS OF '(' type_list ')'---   | a_expr IS NOT OF '(' type_list ')'---   | a_expr BETWEEN opt_asymmetric b_expr AND a_expr---   | a_expr NOT_LA BETWEEN opt_asymmetric b_expr AND a_expr---   | a_expr BETWEEN SYMMETRIC b_expr AND a_expr---   | a_expr NOT_LA BETWEEN SYMMETRIC b_expr AND a_expr---   | a_expr IN_P in_expr---   | a_expr NOT_LA IN_P in_expr---   | a_expr subquery_Op sub_type select_with_parens---   | a_expr subquery_Op sub_type '(' a_expr ')'---   | UNIQUE select_with_parens---   | a_expr IS DOCUMENT_P---   | a_expr IS NOT DOCUMENT_P---   | DEFAULT--- @-data AExpr-  = CExprAExpr CExpr-  | TypecastAExpr AExpr Typename-  | CollateAExpr AExpr AnyName-  | AtTimeZoneAExpr AExpr AExpr-  | PlusAExpr AExpr-  | MinusAExpr AExpr-  | SymbolicBinOpAExpr AExpr SymbolicExprBinOp AExpr-  | PrefixQualOpAExpr QualOp AExpr-  | SuffixQualOpAExpr AExpr QualOp-  | AndAExpr AExpr AExpr-  | OrAExpr AExpr AExpr-  | NotAExpr AExpr-  | VerbalExprBinOpAExpr AExpr Bool VerbalExprBinOp AExpr (Maybe AExpr)-  | ReversableOpAExpr AExpr Bool AExprReversableOp-  | IsnullAExpr AExpr-  | NotnullAExpr AExpr-  | OverlapsAExpr Row Row-  | SubqueryAExpr AExpr SubqueryOp SubType (Either SelectWithParens AExpr)-  | UniqueAExpr SelectWithParens-  | DefaultAExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- b_expr:---   | c_expr---   | b_expr TYPECAST Typename---   | '+' b_expr---   | '-' b_expr---   | b_expr '+' b_expr---   | b_expr '-' b_expr---   | b_expr '*' b_expr---   | b_expr '/' b_expr---   | b_expr '%' b_expr---   | b_expr '^' b_expr---   | b_expr '<' b_expr---   | b_expr '>' b_expr---   | b_expr '=' b_expr---   | b_expr LESS_EQUALS b_expr---   | b_expr GREATER_EQUALS b_expr---   | b_expr NOT_EQUALS b_expr---   | b_expr qual_Op b_expr---   | qual_Op b_expr---   | b_expr qual_Op---   | b_expr IS DISTINCT FROM b_expr---   | b_expr IS NOT DISTINCT FROM b_expr---   | b_expr IS OF '(' type_list ')'---   | b_expr IS NOT OF '(' type_list ')'---   | b_expr IS DOCUMENT_P---   | b_expr IS NOT DOCUMENT_P--- @-data BExpr-  = CExprBExpr CExpr-  | TypecastBExpr BExpr Typename-  | PlusBExpr BExpr-  | MinusBExpr BExpr-  | SymbolicBinOpBExpr BExpr SymbolicExprBinOp BExpr-  | QualOpBExpr QualOp BExpr-  | IsOpBExpr BExpr Bool BExprIsOp-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- c_expr:---   | columnref---   | AexprConst---   | PARAM opt_indirection---   | '(' a_expr ')' opt_indirection---   | case_expr---   | func_expr---   | select_with_parens---   | select_with_parens indirection---   | EXISTS select_with_parens---   | ARRAY select_with_parens---   | ARRAY array_expr---   | explicit_row---   | implicit_row---   | GROUPING '(' expr_list ')'--- @-data CExpr-  = ColumnrefCExpr Columnref-  | AexprConstCExpr AexprConst-  | ParamCExpr Int (Maybe Indirection)-  | InParensCExpr AExpr (Maybe Indirection)-  | CaseCExpr CaseExpr-  | FuncCExpr FuncExpr-  | SelectWithParensCExpr SelectWithParens (Maybe Indirection)-  | ExistsCExpr SelectWithParens-  | ArrayCExpr (Either SelectWithParens ArrayExpr)-  | ExplicitRowCExpr ExplicitRow-  | ImplicitRowCExpr ImplicitRow-  | GroupingCExpr ExprList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- in_expr:---   | select_with_parens---   | '(' expr_list ')'--- @-data InExpr-  = SelectInExpr SelectWithParens-  | ExprListInExpr ExprList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- sub_type:---   | ANY---   | SOME---   | ALL--- @-data SubType = AnySubType | SomeSubType | AllSubType-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)---- |--- ==== References--- @--- array_expr:---   | '[' expr_list ']'---   | '[' array_expr_list ']'---   | '[' ']'--- @-data ArrayExpr-  = ExprListArrayExpr ExprList-  | ArrayExprListArrayExpr ArrayExprList-  | EmptyArrayExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- array_expr_list:---   | array_expr---   | array_expr_list ',' array_expr--- @-type ArrayExprList = NonEmpty ArrayExpr---- |--- ==== References--- @--- row:---   | ROW '(' expr_list ')'---   | ROW '(' ')'---   | '(' expr_list ',' a_expr ')'--- @-data Row-  = ExplicitRowRow ExplicitRow-  | ImplicitRowRow ImplicitRow-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- explicit_row:---   | ROW '(' expr_list ')'---   | ROW '(' ')'--- @-type ExplicitRow = Maybe ExprList---- |--- ==== References--- @--- implicit_row:---   | '(' expr_list ',' a_expr ')'--- @-data ImplicitRow = ImplicitRow ExprList AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_expr:---   | func_application within_group_clause filter_clause over_clause---   | func_expr_common_subexpr--- @-data FuncExpr-  = ApplicationFuncExpr FuncApplication (Maybe WithinGroupClause) (Maybe FilterClause) (Maybe OverClause)-  | SubexprFuncExpr FuncExprCommonSubexpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_expr_windowless:---   | func_application---   | func_expr_common_subexpr--- @-data FuncExprWindowless-  = ApplicationFuncExprWindowless FuncApplication-  | CommonSubexprFuncExprWindowless FuncExprCommonSubexpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- within_group_clause:---   | WITHIN GROUP_P '(' sort_clause ')'---   | EMPTY--- @-type WithinGroupClause = SortClause---- |--- ==== References--- @--- filter_clause:---   | FILTER '(' WHERE a_expr ')'---   | EMPTY--- @-type FilterClause = AExpr---- |--- ==== References--- @--- over_clause:---   | OVER window_specification---   | OVER ColId---   | EMPTY--- @-data OverClause-  = WindowOverClause WindowSpecification-  | ColIdOverClause ColId-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_expr_common_subexpr:---   | COLLATION FOR '(' a_expr ')'---   | CURRENT_DATE---   | CURRENT_TIME---   | CURRENT_TIME '(' Iconst ')'---   | CURRENT_TIMESTAMP---   | CURRENT_TIMESTAMP '(' Iconst ')'---   | LOCALTIME---   | LOCALTIME '(' Iconst ')'---   | LOCALTIMESTAMP---   | LOCALTIMESTAMP '(' Iconst ')'---   | CURRENT_ROLE---   | CURRENT_USER---   | SESSION_USER---   | USER---   | CURRENT_CATALOG---   | CURRENT_SCHEMA---   | CAST '(' a_expr AS Typename ')'---   | EXTRACT '(' extract_list ')'---   | OVERLAY '(' overlay_list ')'---   | POSITION '(' position_list ')'---   | SUBSTRING '(' substr_list ')'---   | TREAT '(' a_expr AS Typename ')'---   | TRIM '(' BOTH trim_list ')'---   | TRIM '(' LEADING trim_list ')'---   | TRIM '(' TRAILING trim_list ')'---   | TRIM '(' trim_list ')'---   | NULLIF '(' a_expr ',' a_expr ')'---   | COALESCE '(' expr_list ')'---   | GREATEST '(' expr_list ')'---   | LEAST '(' expr_list ')'---   | XMLCONCAT '(' expr_list ')'---   | XMLELEMENT '(' NAME_P ColLabel ')'---   | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ')'---   | XMLELEMENT '(' NAME_P ColLabel ',' expr_list ')'---   | XMLELEMENT '(' NAME_P ColLabel ',' xml_attributes ',' expr_list ')'---   | XMLEXISTS '(' c_expr xmlexists_argument ')'---   | XMLFOREST '(' xml_attribute_list ')'---   | XMLPARSE '(' document_or_content a_expr xml_whitespace_option ')'---   | XMLPI '(' NAME_P ColLabel ')'---   | XMLPI '(' NAME_P ColLabel ',' a_expr ')'---   | XMLROOT '(' a_expr ',' xml_root_version opt_xml_root_standalone ')'---   | XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename ')'------ TODO: Implement the XML cases--- @-data FuncExprCommonSubexpr-  = CollationForFuncExprCommonSubexpr AExpr-  | CurrentDateFuncExprCommonSubexpr-  | CurrentTimeFuncExprCommonSubexpr (Maybe Int64)-  | CurrentTimestampFuncExprCommonSubexpr (Maybe Int64)-  | LocalTimeFuncExprCommonSubexpr (Maybe Int64)-  | LocalTimestampFuncExprCommonSubexpr (Maybe Int64)-  | CurrentRoleFuncExprCommonSubexpr-  | CurrentUserFuncExprCommonSubexpr-  | SessionUserFuncExprCommonSubexpr-  | UserFuncExprCommonSubexpr-  | CurrentCatalogFuncExprCommonSubexpr-  | CurrentSchemaFuncExprCommonSubexpr-  | CastFuncExprCommonSubexpr AExpr Typename-  | ExtractFuncExprCommonSubexpr (Maybe ExtractList)-  | OverlayFuncExprCommonSubexpr OverlayList-  | PositionFuncExprCommonSubexpr (Maybe PositionList)-  | SubstringFuncExprCommonSubexpr (Maybe SubstrList)-  | TreatFuncExprCommonSubexpr AExpr Typename-  | TrimFuncExprCommonSubexpr (Maybe TrimModifier) TrimList-  | NullIfFuncExprCommonSubexpr AExpr AExpr-  | CoalesceFuncExprCommonSubexpr ExprList-  | GreatestFuncExprCommonSubexpr ExprList-  | LeastFuncExprCommonSubexpr ExprList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- extract_list:---   | extract_arg FROM a_expr---   | EMPTY--- @-data ExtractList = ExtractList ExtractArg AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- extract_arg:---   | IDENT---   | YEAR_P---   | MONTH_P---   | DAY_P---   | HOUR_P---   | MINUTE_P---   | SECOND_P---   | Sconst--- @-data ExtractArg-  = IdentExtractArg Ident-  | YearExtractArg-  | MonthExtractArg-  | DayExtractArg-  | HourExtractArg-  | MinuteExtractArg-  | SecondExtractArg-  | SconstExtractArg Sconst-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- overlay_list:---   | a_expr overlay_placing substr_from substr_for---   | a_expr overlay_placing substr_from--- @-data OverlayList = OverlayList AExpr OverlayPlacing SubstrFrom (Maybe SubstrFor)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- overlay_placing:---   | PLACING a_expr--- @-type OverlayPlacing = AExpr---- |--- ==== References--- @--- position_list:---   | b_expr IN_P b_expr---   | EMPTY--- @-data PositionList = PositionList BExpr BExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- substr_list:---   | a_expr substr_from substr_for---   | a_expr substr_for substr_from---   | a_expr substr_from---   | a_expr substr_for---   | expr_list---   | EMPTY--- @-data SubstrList-  = ExprSubstrList AExpr SubstrListFromFor-  | ExprListSubstrList ExprList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @---   | a_expr substr_from substr_for---   | a_expr substr_for substr_from---   | a_expr substr_from---   | a_expr substr_for--- @-data SubstrListFromFor-  = FromForSubstrListFromFor SubstrFrom SubstrFor-  | ForFromSubstrListFromFor SubstrFor SubstrFrom-  | FromSubstrListFromFor SubstrFrom-  | ForSubstrListFromFor SubstrFor-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- substr_from:---   | FROM a_expr--- @-type SubstrFrom = AExpr---- |--- ==== References--- @--- substr_for:---   | FOR a_expr--- @-type SubstrFor = AExpr---- |--- ==== References--- @---   | TRIM '(' BOTH trim_list ')'---   | TRIM '(' LEADING trim_list ')'---   | TRIM '(' TRAILING trim_list ')'--- @-data TrimModifier = BothTrimModifier | LeadingTrimModifier | TrailingTrimModifier-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)---- |--- ==== References--- @--- trim_list:---   | a_expr FROM expr_list---   | FROM expr_list---   | expr_list--- @-data TrimList-  = ExprFromExprListTrimList AExpr ExprList-  | FromExprListTrimList ExprList-  | ExprListTrimList ExprList-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- case_expr:---   | CASE case_arg when_clause_list case_default END_P--- @-data CaseExpr = CaseExpr (Maybe CaseArg) WhenClauseList (Maybe CaseDefault)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- case_arg:---   | a_expr---   | EMPTY--- @-type CaseArg = AExpr---- |--- ==== References--- @--- when_clause_list:---   | when_clause---   | when_clause_list when_clause--- @-type WhenClauseList = NonEmpty WhenClause---- |--- ==== References--- @--- case_default:---   | ELSE a_expr---   | EMPTY--- @-type CaseDefault = AExpr---- |--- ==== References--- @--- when_clause:---   |  WHEN a_expr THEN a_expr--- @-data WhenClause = WhenClause AExpr AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_application:---   |  func_name '(' ')'---   |  func_name '(' func_arg_list opt_sort_clause ')'---   |  func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'---   |  func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')'---   |  func_name '(' ALL func_arg_list opt_sort_clause ')'---   |  func_name '(' DISTINCT func_arg_list opt_sort_clause ')'---   |  func_name '(' '*' ')'--- @-data FuncApplication = FuncApplication FuncName (Maybe FuncApplicationParams)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_application:---   |  func_name '(' ')'---   |  func_name '(' func_arg_list opt_sort_clause ')'---   |  func_name '(' VARIADIC func_arg_expr opt_sort_clause ')'---   |  func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')'---   |  func_name '(' ALL func_arg_list opt_sort_clause ')'---   |  func_name '(' DISTINCT func_arg_list opt_sort_clause ')'---   |  func_name '(' '*' ')'--- @-data FuncApplicationParams-  = NormalFuncApplicationParams (Maybe Bool) (NonEmpty FuncArgExpr) (Maybe SortClause)-  | VariadicFuncApplicationParams (Maybe (NonEmpty FuncArgExpr)) FuncArgExpr (Maybe SortClause)-  | StarFuncApplicationParams-  deriving (Show, Generic, Eq, Ord, Data)--data FuncArgExpr-  = ExprFuncArgExpr AExpr-  | ColonEqualsFuncArgExpr Ident AExpr-  | EqualsGreaterFuncArgExpr Ident AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- * Constants--type Sconst = Text--type Iconst = Int64--type Fconst = Double--type Bconst = Text--type Xconst = Text---- |--- AexprConst:---   |  Iconst---   |  FCONST---   |  Sconst---   |  BCONST---   |  XCONST---   |  func_name Sconst---   |  func_name '(' func_arg_list opt_sort_clause ')' Sconst---   |  ConstTypename Sconst---   |  ConstInterval Sconst opt_interval---   |  ConstInterval '(' Iconst ')' Sconst---   |  TRUE_P---   |  FALSE_P---   |  NULL_P-data AexprConst-  = IAexprConst Iconst-  | FAexprConst Fconst-  | SAexprConst Sconst-  | BAexprConst Bconst-  | XAexprConst Xconst-  | FuncAexprConst FuncName (Maybe FuncConstArgs) Sconst-  | ConstTypenameAexprConst ConstTypename Sconst-  | StringIntervalAexprConst Sconst (Maybe Interval)-  | IntIntervalAexprConst Iconst Sconst-  | BoolAexprConst Bool-  | NullAexprConst-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @---   |  func_name '(' func_arg_list opt_sort_clause ')' Sconst--- @-data FuncConstArgs = FuncConstArgs (NonEmpty FuncArgExpr) (Maybe SortClause)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- ConstTypename:---   | Numeric---   | ConstBit---   | ConstCharacter---   | ConstDatetime--- @-data ConstTypename-  = NumericConstTypename Numeric-  | ConstBitConstTypename ConstBit-  | ConstCharacterConstTypename ConstCharacter-  | ConstDatetimeConstTypename ConstDatetime-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- Numeric:---   | INT_P---   | INTEGER---   | SMALLINT---   | BIGINT---   | REAL---   | FLOAT_P opt_float---   | DOUBLE_P PRECISION---   | DECIMAL_P opt_type_modifiers---   | DEC opt_type_modifiers---   | NUMERIC opt_type_modifiers---   | BOOLEAN_P--- opt_float:---   | '(' Iconst ')'---   | EMPTY--- opt_type_modifiers:---   | '(' expr_list ')'---   | EMPTY--- @-data Numeric-  = IntNumeric-  | IntegerNumeric-  | SmallintNumeric-  | BigintNumeric-  | RealNumeric-  | FloatNumeric (Maybe Int64)-  | DoublePrecisionNumeric-  | DecimalNumeric (Maybe TypeModifiers)-  | DecNumeric (Maybe TypeModifiers)-  | NumericNumeric (Maybe TypeModifiers)-  | BooleanNumeric-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- Bit:---   | BitWithLength---   | BitWithoutLength--- ConstBit:---   | BitWithLength---   | BitWithoutLength--- BitWithLength:---   | BIT opt_varying '(' expr_list ')'--- BitWithoutLength:---   | BIT opt_varying--- @-data Bit = Bit OptVarying (Maybe ExprList)-  deriving (Show, Generic, Eq, Ord, Data)--type ConstBit = Bit---- |--- ==== References--- @--- opt_varying:---   | VARYING---   | EMPTY--- @-type OptVarying = Bool---- |--- ==== References--- @--- Character:---   | CharacterWithLength---   | CharacterWithoutLength--- ConstCharacter:---   | CharacterWithLength---   | CharacterWithoutLength--- CharacterWithLength:---   | character '(' Iconst ')'--- CharacterWithoutLength:---   | character--- @-data ConstCharacter = ConstCharacter Character (Maybe Int64)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- character:---   | CHARACTER opt_varying---   | CHAR_P opt_varying---   | VARCHAR---   | NATIONAL CHARACTER opt_varying---   | NATIONAL CHAR_P opt_varying---   | NCHAR opt_varying--- @-data Character-  = CharacterCharacter OptVarying-  | CharCharacter OptVarying-  | VarcharCharacter-  | NationalCharacterCharacter OptVarying-  | NationalCharCharacter OptVarying-  | NcharCharacter OptVarying-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- ConstDatetime:---   | TIMESTAMP '(' Iconst ')' opt_timezone---   | TIMESTAMP opt_timezone---   | TIME '(' Iconst ')' opt_timezone---   | TIME opt_timezone--- @-data ConstDatetime-  = TimestampConstDatetime (Maybe Int64) (Maybe Timezone)-  | TimeConstDatetime (Maybe Int64) (Maybe Timezone)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_timezone:---   | WITH_LA TIME ZONE---   | WITHOUT TIME ZONE---   | EMPTY--- @-type Timezone = Bool---- |--- ==== References--- @--- opt_interval:---   | YEAR_P---   | MONTH_P---   | DAY_P---   | HOUR_P---   | MINUTE_P---   | interval_second---   | YEAR_P TO MONTH_P---   | DAY_P TO HOUR_P---   | DAY_P TO MINUTE_P---   | DAY_P TO interval_second---   | HOUR_P TO MINUTE_P---   | HOUR_P TO interval_second---   | MINUTE_P TO interval_second---   | EMPTY--- @-data Interval-  = YearInterval-  | MonthInterval-  | DayInterval-  | HourInterval-  | MinuteInterval-  | SecondInterval IntervalSecond-  | YearToMonthInterval-  | DayToHourInterval-  | DayToMinuteInterval-  | DayToSecondInterval IntervalSecond-  | HourToMinuteInterval-  | HourToSecondInterval IntervalSecond-  | MinuteToSecondInterval IntervalSecond-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- interval_second:---   | SECOND_P---   | SECOND_P '(' Iconst ')'--- @-type IntervalSecond = Maybe Int64---- * Names & References---- |--- ==== References--- @--- IDENT--- @-data Ident = QuotedIdent Text | UnquotedIdent Text-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- ColId:---   | IDENT---   | unreserved_keyword---   | col_name_keyword--- @-type ColId = Ident---- |--- ==== References--- @--- ColLabel:---   | IDENT---   | unreserved_keyword---   | col_name_keyword---   | type_func_name_keyword---   | reserved_keyword--- @-type ColLabel = Ident---- |--- ==== References--- @--- name:---   | ColId--- @-type Name = ColId---- |--- ==== References--- @--- name_list:---   | name---   | name_list ',' name--- @-type NameList = NonEmpty Name---- |--- ==== References--- @--- cursor_name:---   | name--- @-type CursorName = Name---- |--- ==== References--- @--- columnref:---   | ColId---   | ColId indirection--- @-data Columnref = Columnref ColId (Maybe Indirection)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- any_name:---   | ColId---   | ColId attrs--- @-data AnyName = AnyName ColId (Maybe Attrs)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- func_name:---   | type_function_name---   | ColId indirection--- @-data FuncName-  = TypeFuncName TypeFunctionName-  | IndirectedFuncName ColId Indirection-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- type_function_name:---   | IDENT---   | unreserved_keyword---   | type_func_name_keyword--- @-type TypeFunctionName = Ident---- |--- ==== References--- @--- columnref:---   | ColId---   | ColId indirection--- qualified_name:---   | ColId---   | ColId indirection--- @-data QualifiedName-  = SimpleQualifiedName Ident-  | IndirectedQualifiedName Ident Indirection-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- indirection:---   |  indirection_el---   |  indirection indirection_el--- @-type Indirection = NonEmpty IndirectionEl---- |--- ==== References--- @--- indirection_el:---   |  '.' attr_name---   |  '.' '*'---   |  '[' a_expr ']'---   |  '[' opt_slice_bound ':' opt_slice_bound ']'--- opt_slice_bound:---   |  a_expr---   |  EMPTY--- @-data IndirectionEl-  = AttrNameIndirectionEl Ident-  | AllIndirectionEl-  | ExprIndirectionEl AExpr-  | SliceIndirectionEl (Maybe AExpr) (Maybe AExpr)-  deriving (Show, Generic, Eq, Ord, Data)---- * Types---- |--- Typename definition extended with custom question-marks for nullability specification.------ To match the standard Postgres syntax simply interpret their presence as a parsing error.------ ==== References--- @--- Typename:---   | SimpleTypename opt_array_bounds---   | SETOF SimpleTypename opt_array_bounds---   | SimpleTypename ARRAY '[' Iconst ']'---   | SETOF SimpleTypename ARRAY '[' Iconst ']'---   | SimpleTypename ARRAY---   | SETOF SimpleTypename ARRAY--- @-data Typename-  = Typename-      -- | SETOF-      Bool-      SimpleTypename-      -- | Question mark-      Bool-      -- | Array dimensions possibly followed by a question mark-      (Maybe (TypenameArrayDimensions, Bool))-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- Part of the Typename specification responsible for the choice between the following:---   | opt_array_bounds---   | ARRAY '[' Iconst ']'---   | ARRAY--- @-data TypenameArrayDimensions-  = BoundsTypenameArrayDimensions ArrayBounds-  | ExplicitTypenameArrayDimensions (Maybe Iconst)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_array_bounds:---   | opt_array_bounds '[' ']'---   | opt_array_bounds '[' Iconst ']'---   | EMPTY--- @-type ArrayBounds = NonEmpty (Maybe Iconst)---- |--- ==== References--- @--- SimpleTypename:---   | GenericType---   | Numeric---   | Bit---   | Character---   | ConstDatetime---   | ConstInterval opt_interval---   | ConstInterval '(' Iconst ')'--- ConstInterval:---   | INTERVAL--- @-data SimpleTypename-  = GenericTypeSimpleTypename GenericType-  | NumericSimpleTypename Numeric-  | BitSimpleTypename Bit-  | CharacterSimpleTypename Character-  | ConstDatetimeSimpleTypename ConstDatetime-  | ConstIntervalSimpleTypename (Either (Maybe Interval) Iconst)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- GenericType:---   | type_function_name opt_type_modifiers---   | type_function_name attrs opt_type_modifiers--- @-data GenericType = GenericType TypeFunctionName (Maybe Attrs) (Maybe TypeModifiers)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- attrs:---   | '.' attr_name---   | attrs '.' attr_name--- @-type Attrs = NonEmpty AttrName---- |--- ==== References--- @--- attr_name:---   | ColLabel--- @-type AttrName = ColLabel---- |--- ==== References--- @--- opt_type_modifiers:---   | '(' expr_list ')'---   | EMPTY--- @-type TypeModifiers = ExprList---- |--- ==== References--- @--- type_list:---   | Typename---   | type_list ',' Typename--- @-type TypeList = NonEmpty Typename---- * Operators---- |--- ==== References--- @--- qual_Op:---   | Op---   | OPERATOR '(' any_operator ')'--- @-data QualOp-  = OpQualOp Op-  | OperatorQualOp AnyOperator-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- qual_all_Op:---   | all_Op---   | OPERATOR '(' any_operator ')'--- @-data QualAllOp-  = AllQualAllOp AllOp-  | AnyQualAllOp AnyOperator-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- The operator name is a sequence of up to NAMEDATALEN-1 (63 by default)--- characters from the following list:------ + - * / < > = ~ ! @ # % ^ & | ` ?------ There are a few restrictions on your choice of name:--- -- and /* cannot appear anywhere in an operator name,--- since they will be taken as the start of a comment.------ A multicharacter operator name cannot end in + or -,--- unless the name also contains at least one of these characters:------ ~ ! @ # % ^ & | ` ?------ For example, @- is an allowed operator name, but *- is not.--- This restriction allows PostgreSQL to parse SQL-compliant--- commands without requiring spaces between tokens.--- The use of => as an operator name is deprecated.--- It may be disallowed altogether in a future release.------ The operator != is mapped to <> on input,--- so these two names are always equivalent.--- @-type Op = Text---- |--- ==== References--- @--- any_operator:---   | all_Op---   | ColId '.' any_operator--- @-data AnyOperator-  = AllOpAnyOperator AllOp-  | QualifiedAnyOperator ColId AnyOperator-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- all_Op:---   | Op---   | MathOp--- @-data AllOp-  = OpAllOp Op-  | MathAllOp MathOp-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- MathOp:---   | '+'---   | '-'---   | '*'---   | '/'---   | '%'---   | '^'---   | '<'---   | '>'---   | '='---   | LESS_EQUALS---   | GREATER_EQUALS---   | NOT_EQUALS--- @-data MathOp-  = PlusMathOp-  | MinusMathOp-  | AsteriskMathOp-  | SlashMathOp-  | PercentMathOp-  | ArrowUpMathOp-  | ArrowLeftMathOp-  | ArrowRightMathOp-  | EqualsMathOp-  | LessEqualsMathOp-  | GreaterEqualsMathOp-  | ArrowLeftArrowRightMathOp-  | ExclamationEqualsMathOp-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)--data SymbolicExprBinOp-  = MathSymbolicExprBinOp MathOp-  | QualSymbolicExprBinOp QualOp-  deriving (Show, Generic, Eq, Ord, Data)--data VerbalExprBinOp-  = LikeVerbalExprBinOp-  | IlikeVerbalExprBinOp-  | SimilarToVerbalExprBinOp-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)---- |--- ==== References--- @---   | a_expr IS NULL_P---   | a_expr IS TRUE_P---   | a_expr IS FALSE_P---   | a_expr IS UNKNOWN---   | a_expr IS DISTINCT FROM a_expr---   | a_expr IS OF '(' type_list ')'---   | a_expr BETWEEN opt_asymmetric b_expr AND a_expr---   | a_expr BETWEEN SYMMETRIC b_expr AND a_expr---   | a_expr IN_P in_expr---   | a_expr IS DOCUMENT_P--- @-data AExprReversableOp-  = NullAExprReversableOp-  | TrueAExprReversableOp-  | FalseAExprReversableOp-  | UnknownAExprReversableOp-  | DistinctFromAExprReversableOp AExpr-  | OfAExprReversableOp TypeList-  | BetweenAExprReversableOp Bool BExpr AExpr-  | BetweenSymmetricAExprReversableOp BExpr AExpr-  | InAExprReversableOp InExpr-  | DocumentAExprReversableOp-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @---   | b_expr IS DISTINCT FROM b_expr---   | b_expr IS NOT DISTINCT FROM b_expr---   | b_expr IS OF '(' type_list ')'---   | b_expr IS NOT OF '(' type_list ')'---   | b_expr IS DOCUMENT_P---   | b_expr IS NOT DOCUMENT_P--- @-data BExprIsOp-  = DistinctFromBExprIsOp BExpr-  | OfBExprIsOp TypeList-  | DocumentBExprIsOp-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- subquery_Op:---   | all_Op---   | OPERATOR '(' any_operator ')'---   | LIKE---   | NOT_LA LIKE---   | ILIKE---   | NOT_LA ILIKE--- @-data SubqueryOp-  = AllSubqueryOp AllOp-  | AnySubqueryOp AnyOperator-  | LikeSubqueryOp Bool-  | IlikeSubqueryOp Bool-  deriving (Show, Generic, Eq, Ord, Data)---- * Indexes---- |--- ==== References--- @--- index_params:---   | index_elem---   | index_params ',' index_elem--- @-type IndexParams = NonEmpty IndexElem---- |--- ==== References--- @--- index_elem:---   | ColId opt_collate opt_class opt_asc_desc opt_nulls_order---   | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order---   | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order--- @-data IndexElem = IndexElem IndexElemDef (Maybe Collate) (Maybe Class) (Maybe AscDesc) (Maybe NullsOrder)-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @---   | ColId opt_collate opt_class opt_asc_desc opt_nulls_order---   | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order---   | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order--- @-data IndexElemDef-  = IdIndexElemDef ColId-  | FuncIndexElemDef FuncExprWindowless-  | ExprIndexElemDef AExpr-  deriving (Show, Generic, Eq, Ord, Data)---- |--- ==== References--- @--- opt_collate:---   | COLLATE any_name---   | EMPTY--- @-type Collate = AnyName---- |--- ==== References--- @--- opt_class:---   | any_name---   | EMPTY--- @-type Class = AnyName---- |--- ==== References--- @--- opt_asc_desc:---   | ASC---   | DESC---   | EMPTY--- @-data AscDesc = AscAscDesc | DescAscDesc-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)---- |--- ==== References--- @--- opt_nulls_order:---   | NULLS_LA FIRST_P---   | NULLS_LA LAST_P---   | EMPTY--- @-data NullsOrder = FirstNullsOrder | LastNullsOrder-  deriving (Show, Generic, Eq, Ord, Data, Enum, Bounded)
− library/PostgresqlSyntax/CharSet.hs
@@ -1,21 +0,0 @@-module PostgresqlSyntax.CharSet where--import qualified Data.Text as Text-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import PostgresqlSyntax.Prelude--{-# NOINLINE symbolicBinOp #-}-symbolicBinOp :: HashSet Char-symbolicBinOp = KeywordSet.symbolicBinOp & toList & mconcat & Text.unpack & fromList--{-# NOINLINE hexDigit #-}-hexDigit :: HashSet Char-hexDigit = fromList "0123456789abcdefABCDEF"--{-# NOINLINE op #-}-op :: HashSet Char-op = fromList "+-*/<>=~!@#%^&|`?"--{-# NOINLINE prohibitionLiftingOp #-}-prohibitionLiftingOp :: HashSet Char-prohibitionLiftingOp = fromList "~!@#%^&|`?"
− library/PostgresqlSyntax/Extras/HeadedMegaparsec.hs
@@ -1,118 +0,0 @@-{-# OPTIONS_GHC -Wno-redundant-constraints -Wno-dodgy-imports -Wno-unused-imports #-}---- |--- Generic helpers for HeadedMegaparsec.-module PostgresqlSyntax.Extras.HeadedMegaparsec where--import Control.Applicative.Combinators hiding (some)-import Control.Applicative.Combinators.NonEmpty-import qualified Data.Text as Text-import HeadedMegaparsec hiding (string)-import PostgresqlSyntax.Prelude hiding (bit, expr, filter, head, many, option, some, sortBy, tail, try)-import Text.Megaparsec (Parsec, Stream, TraversableStream, VisualStream)-import qualified Text.Megaparsec as Megaparsec-import qualified Text.Megaparsec.Char as MegaparsecChar-import qualified Text.Megaparsec.Char.Lexer as MegaparsecLexer---- $setup--- >>> testParser parser = either putStr print . run parser---- * Executors--run :: (Ord err, VisualStream strm, TraversableStream strm, Megaparsec.ShowErrorComponent err) => HeadedParsec err strm a -> strm -> Either String a-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---- |--- Lifted megaparsec\'s `Megaparsec.eof`.-eof :: (Ord err, Stream strm) => HeadedParsec err strm ()-eof = parse Megaparsec.eof---- |--- Lifted megaparsec\'s `Megaparsec.space`.-space :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm ()-space = parse MegaparsecChar.space---- |--- Lifted megaparsec\'s `Megaparsec.space1`.-space1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm ()-space1 = parse MegaparsecChar.space1---- |--- Lifted megaparsec\'s `Megaparsec.char`.-char :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => Char -> HeadedParsec err strm Char-char a = parse (MegaparsecChar.char a)---- |--- Lifted megaparsec\'s `Megaparsec.char'`.-char' :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => Char -> HeadedParsec err strm Char-char' a = parse (MegaparsecChar.char' a)---- |--- Lifted megaparsec\'s `Megaparsec.string`.-string :: (Ord err, Stream strm) => Megaparsec.Tokens strm -> HeadedParsec err strm (Megaparsec.Tokens strm)-string = parse . MegaparsecChar.string---- |--- Lifted megaparsec\'s `Megaparsec.string'`.-string' :: (Ord err, Stream strm, FoldCase (Megaparsec.Tokens strm)) => Megaparsec.Tokens strm -> HeadedParsec err strm (Megaparsec.Tokens strm)-string' = parse . MegaparsecChar.string'---- |--- Lifted megaparsec\'s `Megaparsec.takeWhileP`.-takeWhileP :: (Ord err, Stream strm) => Maybe String -> (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Tokens strm)-takeWhileP label predicate = parse (Megaparsec.takeWhileP label predicate)---- |--- Lifted megaparsec\'s `Megaparsec.takeWhile1P`.-takeWhile1P :: (Ord err, Stream strm) => Maybe String -> (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Tokens strm)-takeWhile1P label predicate = parse (Megaparsec.takeWhile1P label predicate)--satisfy :: (Ord err, Stream strm) => (Megaparsec.Token strm -> Bool) -> HeadedParsec err strm (Megaparsec.Token strm)-satisfy = parse . Megaparsec.satisfy--decimal :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char, Integral decimal) => HeadedParsec err strm decimal-decimal = parse MegaparsecLexer.decimal--float :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char, RealFloat float) => HeadedParsec err strm float-float = parse MegaparsecLexer.float---- * Combinators--sep1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm separtor -> HeadedParsec err strm a -> HeadedParsec err strm (NonEmpty a)-sep1 separator parser = do-  head <- parser-  endHead-  tail <- many $ separator *> parser-  return (head :| tail)--sepEnd1 :: (Ord err, Stream strm, Megaparsec.Token strm ~ Char) => HeadedParsec err strm separator -> HeadedParsec err strm end -> HeadedParsec err strm el -> HeadedParsec err strm (NonEmpty el, end)-sepEnd1 sepP endP elP = do-  headEl <- elP-  let loop !list = do-        _ <- sepP-        asum-          [ do-              end <- endP-              return (headEl :| reverse list, end),-            do-              el <- elP-              loop (el : list)-          ]-   in loop []--notFollowedBy :: (Ord err, Stream strm) => HeadedParsec err strm a -> HeadedParsec err strm ()-notFollowedBy a = parse (Megaparsec.notFollowedBy (toParsec a))
− library/PostgresqlSyntax/Extras/NonEmpty.hs
@@ -1,33 +0,0 @@-{-# OPTIONS_GHC -Wno-dodgy-imports #-}--module PostgresqlSyntax.Extras.NonEmpty where--import Data.List.NonEmpty-import PostgresqlSyntax.Prelude hiding (cons, fromList, head, init, last, reverse, tail, uncons)---- |--- >>> intersperseFoldMap ", " id (fromList ["a"])--- "a"------ >>> intersperseFoldMap ", " id (fromList ["a", "b", "c"])--- "a, b, c"-intersperseFoldMap :: (Monoid m) => m -> (a -> m) -> NonEmpty a -> m-intersperseFoldMap a b (c :| d) = b c <> foldMap (mappend a . b) d--unsnoc :: NonEmpty a -> (Maybe (NonEmpty a), a)-unsnoc =-  let build1 = \case-        a :| b -> build2 a b-      build2 a = \case-        b : c -> build3 b (a :| []) c-        _ -> (Nothing, a)-      build3 a b = \case-        c : d -> build3 c (cons a b) d-        _ -> (Just (reverse b), a)-   in build1--consAndUnsnoc :: a -> NonEmpty a -> (NonEmpty a, a)-consAndUnsnoc a b = case unsnoc b of-  (c, d) -> case c of-    Just e -> (cons a e, d)-    Nothing -> (pure a, d)
− library/PostgresqlSyntax/Extras/TextBuilder.hs
@@ -1,16 +0,0 @@-module PostgresqlSyntax.Extras.TextBuilder where--import PostgresqlSyntax.Prelude-import TextBuilder--char7 :: Char -> TextBuilder-char7 = char--intDec :: Int -> TextBuilder-intDec = decimal--int64Dec :: Int64 -> TextBuilder-int64Dec = decimal--doubleDec :: Double -> TextBuilder-doubleDec = fromString . show
− library/PostgresqlSyntax/KeywordSet.hs
@@ -1,66 +0,0 @@-module PostgresqlSyntax.KeywordSet where--import Data.HashSet-import PostgresqlSyntax.Prelude hiding (fromList, toList)--{-# NOINLINE keyword #-}-{--From https://github.com/postgres/postgres/blob/1aac32df89eb19949050f6f27c268122833ad036/src/include/parser/kwlist.h--}-keyword :: HashSet Text-keyword = fromList ["abort", "absolute", "access", "action", "add", "admin", "after", "aggregate", "all", "also", "alter", "always", "analyse", "analyze", "and", "any", "array", "as", "asc", "assertion", "assignment", "asymmetric", "at", "attach", "attribute", "authorization", "backward", "before", "begin", "between", "bigint", "binary", "bit", "boolean", "both", "by", "cache", "call", "called", "cascade", "cascaded", "case", "cast", "catalog", "chain", "char", "character", "characteristics", "check", "checkpoint", "class", "close", "cluster", "coalesce", "collate", "collation", "column", "columns", "comment", "comments", "commit", "committed", "concurrently", "configuration", "conflict", "connection", "constraint", "constraints", "content", "continue", "conversion", "copy", "cost", "create", "cross", "csv", "cube", "current", "current_catalog", "current_date", "current_role", "current_schema", "current_time", "current_timestamp", "current_user", "cursor", "cycle", "data", "database", "day", "deallocate", "dec", "decimal", "declare", "default", "defaults", "deferrable", "deferred", "definer", "delete", "delimiter", "delimiters", "depends", "desc", "detach", "dictionary", "disable", "discard", "distinct", "do", "document", "domain", "double", "drop", "each", "else", "enable", "encoding", "encrypted", "end", "enum", "escape", "event", "except", "exclude", "excluding", "exclusive", "execute", "exists", "explain", "expression", "extension", "external", "extract", "false", "family", "fetch", "filter", "first", "float", "following", "for", "force", "foreign", "forward", "freeze", "from", "full", "function", "functions", "generated", "global", "grant", "granted", "greatest", "group", "grouping", "groups", "handler", "having", "header", "hold", "hour", "identity", "if", "ilike", "immediate", "immutable", "implicit", "import", "in", "include", "including", "increment", "index", "indexes", "inherit", "inherits", "initially", "inline", "inner", "inout", "input", "insensitive", "insert", "instead", "int", "integer", "intersect", "interval", "into", "invoker", "is", "isnull", "isolation", "join", "key", "label", "language", "large", "last", "lateral", "leading", "leakproof", "least", "left", "level", "like", "limit", "listen", "load", "local", "localtime", "localtimestamp", "location", "lock", "locked", "logged", "mapping", "match", "materialized", "maxvalue", "method", "minute", "minvalue", "mode", "month", "move", "name", "names", "national", "natural", "nchar", "new", "next", "nfc", "nfd", "nfkc", "nfkd", "no", "none", "normalize", "normalized", "not", "nothing", "notify", "notnull", "nowait", "null", "nullif", "nulls", "numeric", "object", "of", "off", "offset", "oids", "old", "on", "only", "operator", "option", "options", "or", "order", "ordinality", "others", "out", "outer", "over", "overlaps", "overlay", "overriding", "owned", "owner", "parallel", "parser", "partial", "partition", "passing", "password", "placing", "plans", "policy", "position", "preceding", "precision", "prepare", "prepared", "preserve", "primary", "prior", "privileges", "procedural", "procedure", "procedures", "program", "publication", "quote", "range", "read", "real", "reassign", "recheck", "recursive", "ref", "references", "referencing", "refresh", "reindex", "relative", "release", "rename", "repeatable", "replace", "replica", "reset", "restart", "restrict", "returning", "returns", "revoke", "right", "role", "rollback", "rollup", "routine", "routines", "row", "rows", "rule", "savepoint", "schema", "schemas", "scroll", "search", "second", "security", "select", "sequence", "sequences", "serializable", "server", "session", "session_user", "set", "setof", "sets", "share", "show", "similar", "simple", "skip", "smallint", "snapshot", "some", "sql", "stable", "standalone", "start", "statement", "statistics", "stdin", "stdout", "storage", "stored", "strict", "strip", "subscription", "substring", "support", "symmetric", "sysid", "system", "table", "tables", "tablesample", "tablespace", "temp", "template", "temporary", "text", "then", "ties", "time", "timestamp", "to", "trailing", "transaction", "transform", "treat", "trigger", "trim", "true", "truncate", "trusted", "type", "types", "uescape", "unbounded", "uncommitted", "unencrypted", "union", "unique", "unknown", "unlisten", "unlogged", "until", "update", "user", "using", "vacuum", "valid", "validate", "validator", "value", "values", "varchar", "variadic", "varying", "verbose", "version", "view", "views", "volatile", "when", "where", "whitespace", "window", "with", "within", "without", "work", "wrapper", "write", "xml", "xmlattributes", "xmlconcat", "xmlelement", "xmlexists", "xmlforest", "xmlnamespaces", "xmlparse", "xmlpi", "xmlroot", "xmlserialize", "xmltable", "year", "yes", "zone"]--{-# NOINLINE unreservedKeyword #-}-unreservedKeyword :: HashSet Text-unreservedKeyword = fromList ["abort", "absolute", "access", "action", "add", "admin", "after", "aggregate", "also", "alter", "always", "assertion", "assignment", "at", "attach", "attribute", "backward", "before", "begin", "by", "cache", "call", "called", "cascade", "cascaded", "catalog", "chain", "characteristics", "checkpoint", "class", "close", "cluster", "columns", "comment", "comments", "commit", "committed", "configuration", "conflict", "connection", "constraints", "content", "continue", "conversion", "copy", "cost", "csv", "cube", "current", "cursor", "cycle", "data", "database", "day", "deallocate", "declare", "defaults", "deferred", "definer", "delete", "delimiter", "delimiters", "depends", "detach", "dictionary", "disable", "discard", "document", "domain", "double", "drop", "each", "enable", "encoding", "encrypted", "enum", "escape", "event", "exclude", "excluding", "exclusive", "execute", "explain", "extension", "external", "family", "filter", "first", "following", "force", "forward", "function", "functions", "generated", "global", "granted", "groups", "handler", "header", "hold", "hour", "identity", "if", "immediate", "immutable", "implicit", "import", "include", "including", "increment", "index", "indexes", "inherit", "inherits", "inline", "input", "insensitive", "insert", "instead", "invoker", "isolation", "key", "label", "language", "large", "last", "leakproof", "level", "listen", "load", "local", "location", "lock", "locked", "logged", "mapping", "match", "materialized", "maxvalue", "method", "minute", "minvalue", "mode", "month", "move", "name", "names", "new", "next", "no", "nothing", "notify", "nowait", "nulls", "object", "of", "off", "oids", "old", "operator", "option", "options", "ordinality", "others", "over", "overriding", "owned", "owner", "parallel", "parser", "partial", "partition", "passing", "password", "plans", "policy", "preceding", "prepare", "prepared", "preserve", "prior", "privileges", "procedural", "procedure", "procedures", "program", "publication", "quote", "range", "read", "reassign", "recheck", "recursive", "ref", "referencing", "refresh", "reindex", "relative", "release", "rename", "repeatable", "replace", "replica", "reset", "restart", "restrict", "returns", "revoke", "role", "rollback", "rollup", "routine", "routines", "rows", "rule", "savepoint", "schema", "schemas", "scroll", "search", "second", "security", "sequence", "sequences", "serializable", "server", "session", "set", "sets", "share", "show", "simple", "skip", "snapshot", "sql", "stable", "standalone", "start", "statement", "statistics", "stdin", "stdout", "storage", "stored", "strict", "strip", "subscription", "support", "sysid", "system", "tables", "tablespace", "temp", "template", "temporary", "text", "ties", "transaction", "transform", "trigger", "truncate", "trusted", "type", "types", "unbounded", "uncommitted", "unencrypted", "unknown", "unlisten", "unlogged", "until", "update", "vacuum", "valid", "validate", "validator", "value", "varying", "version", "view", "views", "volatile", "whitespace", "within", "without", "work", "wrapper", "write", "xml", "year", "yes", "zone"]--{-# NOINLINE colNameKeyword #-}-colNameKeyword :: HashSet Text-colNameKeyword = fromList ["between", "bigint", "bit", "boolean", "char", "character", "coalesce", "dec", "decimal", "exists", "extract", "float", "greatest", "grouping", "inout", "int", "integer", "interval", "least", "national", "nchar", "none", "normalize", "nullif", "numeric", "out", "overlay", "position", "precision", "real", "row", "setof", "smallint", "substring", "time", "timestamp", "treat", "trim", "values", "varchar", "xmlattributes", "xmlconcat", "xmlelement", "xmlexists", "xmlforest", "xmlnamespaces", "xmlparse", "xmlpi", "xmlroot", "xmlserialize", "xmltable"]--{-# NOINLINE typeFuncNameKeyword #-}-typeFuncNameKeyword :: HashSet Text-typeFuncNameKeyword = fromList ["authorization", "binary", "collation", "concurrently", "cross", "current_schema", "freeze", "full", "ilike", "inner", "is", "isnull", "join", "left", "like", "natural", "notnull", "outer", "overlaps", "right", "similar", "tablesample", "verbose"]--{-# NOINLINE reservedKeyword #-}-reservedKeyword :: HashSet Text-reservedKeyword = fromList ["all", "analyse", "analyze", "and", "any", "array", "as", "asc", "asymmetric", "both", "case", "cast", "check", "collate", "column", "constraint", "create", "current_catalog", "current_date", "current_role", "current_time", "current_timestamp", "current_user", "default", "deferrable", "desc", "distinct", "do", "else", "end", "except", "false", "fetch", "for", "foreign", "from", "grant", "group", "having", "in", "initially", "intersect", "into", "lateral", "leading", "limit", "localtime", "localtimestamp", "not", "null", "offset", "on", "only", "or", "order", "placing", "primary", "references", "returning", "select", "session_user", "some", "symmetric", "table", "then", "to", "trailing", "true", "union", "unique", "user", "using", "variadic", "when", "where", "window", "with"]--{-# NOINLINE symbolicBinOp #-}-symbolicBinOp :: HashSet Text-symbolicBinOp = fromList ["+", "-", "*", "/", "%", "^", "<", ">", "=", "<=", ">=", "<>", "~~", "~~*", "!~~", "!~~*", "~", "~*", "!~", "!~*"]--{-# NOINLINE lexicalBinOp #-}-lexicalBinOp :: HashSet Text-lexicalBinOp = fromList ["and", "or"]--{-# NOINLINE colId #-}-colId :: HashSet Text-colId = unions [unreservedKeyword, colNameKeyword]--{--type_function_name:-  | IDENT-  | unreserved_keyword-  | type_func_name_keyword--}-{-# NOINLINE typeFunctionName #-}-typeFunctionName :: HashSet Text-typeFunctionName = unions [unreservedKeyword, typeFuncNameKeyword]---- |--- As per the following comment from the original scanner definition:------ /*---  * Likewise, if what we have left is two chars, and---  * those match the tokens ">=", "<=", "=>", "<>" or---  * "!=", then we must return the appropriate token---  * rather than the generic Op.---  */-{-# NOINLINE nonOp #-}-nonOp :: HashSet Text-nonOp = fromList [">=", "<=", "=>", "<>", "!="] <> mathOp--{-# NOINLINE mathOp #-}-mathOp :: HashSet Text-mathOp = fromList ["<>", ">=", "!=", "<=", "+", "-", "*", "/", "%", "^", "<", ">", "="]
− library/PostgresqlSyntax/Parsing.hs
@@ -1,2290 +0,0 @@-{-# OPTIONS_GHC -Wno-redundant-constraints -Wno-missing-signatures -Wno-dodgy-imports #-}---- |------ Our parsing strategy is to port the original Postgres parser as closely as possible.------ We're using the @gram.y@ Postgres source file, which is the closest thing we have--- to a Postgres syntax spec. Here's a link to it:--- https://github.com/postgres/postgres/blob/master/src/backend/parser/gram.y.------ Here's the essence of how the original parser is implemented, citing from--- [PostgreSQL Wiki](https://wiki.postgresql.org/wiki/Developer_FAQ):------     scan.l defines the lexer, i.e. the algorithm that splits a string---     (containing an SQL statement) into a stream of tokens.---     A token is usually a single word---     (i.e., doesn't contain spaces but is delimited by spaces),---     but can also be a whole single or double-quoted string for example.---     The lexer is basically defined in terms of regular expressions---     which describe the different token types.------     gram.y defines the grammar (the syntactical structure) of SQL statements,---     using the tokens generated by the lexer as basic building blocks.---     The grammar is defined in BNF notation.---     BNF resembles regular expressions but works on the level of tokens, not characters.---     Also, patterns (called rules or productions in BNF) are named, and may be recursive,---     i.e. use themselves as sub-patterns.-module PostgresqlSyntax.Parsing where--import Control.Applicative.Combinators hiding (some)-import Control.Applicative.Combinators.NonEmpty-import qualified Data.HashSet as HashSet-import qualified Data.Text as Text-import HeadedMegaparsec hiding (string)-import PostgresqlSyntax.Ast-import PostgresqlSyntax.Extras.HeadedMegaparsec hiding (run)-import qualified PostgresqlSyntax.Extras.HeadedMegaparsec as Extras-import qualified PostgresqlSyntax.Extras.NonEmpty as NonEmpty-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import qualified PostgresqlSyntax.Predicate as Predicate-import PostgresqlSyntax.Prelude hiding (bit, expr, filter, fromList, head, many, option, some, sortBy, tail, try)-import qualified PostgresqlSyntax.Validation as Validation-import qualified Text.Megaparsec as Megaparsec-import qualified Text.Megaparsec.Char as MegaparsecChar-import qualified TextBuilder---- $setup--- >>> testParser parser = either putStr print . run parser--type Parser = HeadedParsec Void Text---- * Executors--run :: Parser a -> Text -> Either String a-run = Extras.run--runWithPosError :: Parser a -> Text -> Either (NonEmpty (Int, String)) a-runWithPosError = Extras.runParserWithErrorPos---- * Helpers--inSpace :: Parser a -> Parser a-inSpace p = space *> p <* space--commaSeparator :: Parser ()-commaSeparator = space *> char ',' *> endHead *> space--dotSeparator :: Parser ()-dotSeparator = space *> char '.' *> endHead *> space--inBrackets :: Parser a -> Parser a-inBrackets p = char '[' *> space *> p <* endHead <* space <* char ']'--inBracketsCont :: Parser a -> Parser (Parser a)-inBracketsCont p = char '[' *> endHead *> pure (space *> p <* endHead <* space <* char ']')--inParens :: Parser a -> Parser a-inParens p = char '(' *> space *> p <* endHead <* space <* char ')'--inParensCont :: Parser a -> Parser (Parser a)-inParensCont p = char '(' *> endHead *> pure (space *> p <* endHead <* space <* char ')')--inParensWithLabel :: (label -> content -> result) -> Parser label -> Parser content -> Parser result-inParensWithLabel result labelParser contentParser = do-  label <- wrapToHead labelParser-  space-  char '('-  endHead-  space-  content <- contentParser-  space-  char ')'-  pure (result label content)--inParensWithClause :: Parser clause -> Parser content -> Parser content-inParensWithClause = inParensWithLabel (const id)--trueIfPresent :: Parser a -> Parser Bool-trueIfPresent p = option False (True <$ p)---- |--- >>> testParser (quotedString '\'') "'abc''d'"--- "abc'd"-quotedString :: Char -> Parser Text-quotedString q = do-  char q-  endHead-  tail <--    parse-      $ let collectChunks !bdr = do-              chunk <- Megaparsec.takeWhileP Nothing (/= q)-              let bdr' = bdr <> TextBuilder.text chunk-              Megaparsec.try (consumeEscapedQuote bdr') <|> finish bdr'-            consumeEscapedQuote bdr = do-              MegaparsecChar.char q-              MegaparsecChar.char q-              collectChunks (bdr <> TextBuilder.char q)-            finish bdr = do-              MegaparsecChar.char q-              return (TextBuilder.toText bdr)-         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---- * PreparableStmt--preparableStmt =-  asum-    [ SelectPreparableStmt <$> selectStmt,-      InsertPreparableStmt <$> insertStmt,-      UpdatePreparableStmt <$> updateStmt,-      DeletePreparableStmt <$> deleteStmt,-      CallPreparableStmt <$> callStmt-    ]---- * Call--callStmt = do-  keyword "call"-  space1-  CallStmt <$> funcApplication---- * Insert--insertStmt = do-  a <- optional (wrapToHead withClause <* space1)-  keyword "insert"-  space1-  endHead-  keyword "into"-  space1-  b <- insertTarget-  space1-  c <- insertRest-  d <- optional (space1 *> onConflict)-  e <- optional (space1 *> returningClause)-  return (InsertStmt a b c d e)--insertTarget = do-  a <- qualifiedName-  endHead-  b <- optional (space1 *> keyword "as" *> space1 *> endHead *> colId)-  return (InsertTarget a b)--insertRest =-  asum-    [ DefaultValuesInsertRest <$ (keyword "default" *> space1 *> endHead *> keyword "values"),-      do-        a <- optional (inParens insertColumnList <* space1)-        b <- optional $ do-          keyword "overriding"-          space1-          endHead-          b <- overrideKind-          space1-          keyword "value"-          space1-          return b-        c <- selectStmt-        return (SelectInsertRest a b c)-    ]--overrideKind =-  asum-    [ UserOverrideKind <$ keyword "user",-      SystemOverrideKind <$ keyword "system"-    ]--insertColumnList = sep1 commaSeparator insertColumnItem--insertColumnItem = do-  a <- colId-  endHead-  b <- optional (space1 *> indirection)-  return (InsertColumnItem a b)--onConflict = do-  keyword "on"-  space1-  keyword "conflict"-  space1-  endHead-  a <- optional (confExpr <* space1)-  keyword "do"-  space1-  b <- onConflictDo-  return (OnConflict a b)--confExpr =-  asum-    [ WhereConfExpr <$> inParens indexParams <*> optional (space *> whereClause),-      ConstraintConfExpr <$> (keyword "on" *> space1 *> keyword "constraint" *> space1 *> endHead *> name)-    ]--onConflictDo =-  asum-    [ NothingOnConflictDo <$ keyword "nothing",-      do-        keyword "update"-        space1-        endHead-        keyword "set"-        space1-        a <- setClauseList-        b <- optional (space1 *> whereClause)-        return (UpdateOnConflictDo a b)-    ]--returningClause = do-  keyword "returning"-  space1-  endHead-  targetList---- * Update--updateStmt = do-  a <- optional (wrapToHead withClause <* space1)-  keyword "update"-  space1-  endHead-  b <- relationExprOptAlias ["set"]-  space1-  keyword "set"-  space1-  c <- setClauseList-  d <- optional (space1 *> fromClause)-  e <- optional (space1 *> whereOrCurrentClause)-  f <- optional (space1 *> returningClause)-  return (UpdateStmt a b c d e f)--setClauseList = sep1 commaSeparator setClause--setClause =-  asum-    [ do-        a <- inParens setTargetList-        space-        char '='-        space-        b <- aExpr-        return (TargetListSetClause a b),-      do-        a <- setTarget-        space-        char '='-        space-        b <- aExpr-        return (TargetSetClause a b)-    ]--setTarget = do-  a <- colId-  endHead-  b <- optional (space1 *> indirection)-  return (SetTarget a b)--setTargetList = sep1 commaSeparator setTarget---- * Delete--deleteStmt = do-  a <- optional (wrapToHead withClause <* space1)-  keyword "delete"-  space1-  endHead-  keyword "from"-  space1-  b <- relationExprOptAlias ["using", "where", "returning"]-  c <- optional (space1 *> usingClause)-  d <- optional (space1 *> whereOrCurrentClause)-  e <- optional (space1 *> returningClause)-  return (DeleteStmt a b c d e)--usingClause = do-  keyword "using"-  space1-  fromList---- * Select---- |--- >>> test = testParser selectStmt------ >>> test "select id from as"--- ...---   |--- 1 | select id from as---   |                  ^--- Reserved keyword "as" used as an identifier. If that's what you intend, you have to wrap it in double quotes.-selectStmt = Left <$> selectNoParens <|> Right <$> selectWithParens--selectWithParens = inParens selectWithParensBody---- |--- The content of a @select_with_parens@, after the opening paren.------ @gram.y@ gives two productions, @'(' select_with_parens ')'@ and--- @'(' select_no_parens ')'@, and they overlap: a @select_no_parens@ may--- itself be nothing but a @select_clause@, and a @select_clause@ may itself be--- a @select_with_parens@. Transcribed literally as two alternatives, that--- overlap makes every nested paren group get parsed twice — once down the--- @select_with_parens@ branch and once down the @select_no_parens@ branch —--- so the cost doubles with each level of nesting. That was the dominant term--- in the exponential blowup this parser used to exhibit on parenthesised--- input, including input that is not a select at all (the two branches both--- have to descend the whole nest before either can fail).------ So the shared prefix is parsed once and classified afterwards.------ ==== Canonical shape------ Because the productions overlap, @((select 1))@ has two representations:--- @WithParensSelectWithParens@ wrapping the inner parenthesised select, or--- @NoParensSelectWithParens@ of a @SelectNoParens@ whose clause is that same--- inner parenthesised select. Both render back to the same text.------ __The first is canonical.__ A parenthesised select with nothing else--- attached to it is a @WithParensSelectWithParens@; the--- @NoParensSelectWithParens@ form is produced only when the parens are--- actually carrying something — a set operation (@union@ and friends), a sort--- clause, a limit, or a locking clause. That is the collapse performed by the--- @case@ below, and it is what the property-test generators are aligned with.-selectWithParensBody =-  asum-    [ do-        a <- wrapToHead selectWithParens-        b <- selectNoParensAfterClause Nothing (Right a)-        return $ case b of-          SelectNoParens Nothing (Right c) Nothing Nothing Nothing -> WithParensSelectWithParens c-          _ -> NoParensSelectWithParens b,-      NoParensSelectWithParens <$> unparenthesizedSelectNoParens-    ]--selectNoParens = withSelectNoParens <|> simpleSelectNoParens---- |--- 'selectNoParens' restricted to the forms that do not begin with @(@.------ Used by 'selectWithParensBody', where the paren-leading form is already--- covered by the branch that shares the nested 'selectWithParens' parse.--- Admitting it here again is what would reintroduce the doubling.-unparenthesizedSelectNoParens =-  withSelectNoParens-    <|> (baseSimpleSelect >>= selectNoParensAfterClause Nothing . Left)--sharedSelectNoParens with = selectClauseBase >>= selectNoParensAfterClause with---- |--- The remainder of 'sharedSelectNoParens', resumed from an already parsed--- 'selectClauseBase'. Split out so that callers which have had to parse that--- base themselves can continue without parsing it again.-selectNoParensAfterClause with clauseBase = do-  select <- extendMany selectClauseSuffix clauseBase-  sort <- optional (space1 *> sortClause)-  (limit, forLocking) <- limitFirst <|> forLockingFirst <|> pure (Nothing, Nothing)-  return (SelectNoParens with select sort limit forLocking)-  where-    limitFirst = do-      limit <- space1 *> selectLimit-      forLocking <- optional (space1 *> forLockingClause)-      pure (Just limit, forLocking)-    forLockingFirst = do-      forLocking <- space1 *> forLockingClause-      limit <- optional (space1 *> selectLimit)-      pure (limit, Just forLocking)---- |--- The one that doesn't start with \"WITH\".------ ==== References--- @---   | simple_select---   | select_clause sort_clause---   | select_clause opt_sort_clause for_locking_clause opt_select_limit---   | select_clause opt_sort_clause select_limit opt_for_locking_clause--- @-simpleSelectNoParens = sharedSelectNoParens Nothing--withSelectNoParens = do-  with <- wrapToHead withClause-  space1-  sharedSelectNoParens (Just with)--selectClause = selectClauseBase >>= extendMany selectClauseSuffix--selectClauseBase =-  asum-    [ Right <$> selectWithParens,-      Left <$> baseSimpleSelect-    ]--selectClauseSuffix a = Left <$> extensionSimpleSelect a--baseSimpleSelect =-  asum-    [ do-        keyword "select"-        notFollowedBy $ satisfy $ isAlphaNum-        endHead-        targeting <- optional (space1 *> targeting)-        intoClause <- optional (space1 *> keyword "into" *> endHead *> space1 *> optTempTableName)-        fromClause <- optional (space1 *> fromClause)-        whereClause <- optional (space1 *> whereClause)-        groupClause <- optional (space1 *> keyphrase "group by" *> endHead *> space1 *> sep1 commaSeparator groupByItem)-        havingClause <- optional (space1 *> keyword "having" *> endHead *> space1 *> aExpr)-        windowClause <- optional (space1 *> keyword "window" *> endHead *> space1 *> sep1 commaSeparator windowDefinition)-        return (NormalSimpleSelect targeting intoClause fromClause whereClause groupClause havingClause windowClause),-      do-        keyword "table"-        space1-        endHead-        TableSimpleSelect <$> relationExpr,-      ValuesSimpleSelect <$> valuesClause-    ]--extensionSimpleSelect headSelectClause = do-  op <- space1 *> selectBinOp <* space1-  endHead-  allOrDistinct <- optional (allOrDistinct <* space1)-  selectClause <- selectClause-  return (BinSimpleSelect op headSelectClause allOrDistinct selectClause)--allOrDistinct = keyword "all" $> False <|> keyword "distinct" $> True--selectBinOp =-  asum-    [ keyword "union" $> UnionSelectBinOp,-      keyword "intersect" $> IntersectSelectBinOp,-      keyword "except" $> ExceptSelectBinOp-    ]--valuesClause = do-  keyword "values"-  space-  sep1 commaSeparator $ do-    char '('-    endHead-    space-    a <- sep1 commaSeparator aExpr-    space-    char ')'-    return a--withClause = label "with clause" $ do-  keyword "with"-  space1-  endHead-  recursive <- option False (True <$ keyword "recursive" <* space1)-  cteList <- sep1 commaSeparator commonTableExpr-  return (WithClause recursive cteList)--commonTableExpr = label "common table expression" $ do-  name <- colId <* space <* endHead-  nameList <- optional (inParens (sep1 commaSeparator colId) <* space1)-  keyword "as"-  space1-  materialized <- optional (materialized <* space1)-  stmt <- inParens preparableStmt-  return (CommonTableExpr name nameList materialized stmt)--materialized =-  True <$ keyword "materialized"-    <|> False <$ keyphrase "not materialized"--targeting = distinct <|> allWithTargetList <|> all <|> normal-  where-    normal = NormalTargeting <$> targetList-    allWithTargetList = do-      keyword "all"-      space1-      AllTargeting <$> Just <$> targetList-    all = keyword "all" $> AllTargeting Nothing-    distinct = do-      keyword "distinct"-      space1-      endHead-      optOn <- optional (onExpressionsClause <* space1)-      targetList <- targetList-      return (DistinctTargeting optOn targetList)--targetList = sep1 commaSeparator targetEl---- |--- >>> testParser targetEl "a.b as c"--- AliasedExprTargetEl (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "a") (Just (AttrNameIndirectionEl (UnquotedIdent "b") :| []))))) (UnquotedIdent "c")-targetEl =-  label "target"-    $ asum-      [ do-          expr <- aExpr-          asum-            [ do-                space1-                asum-                  [ AliasedExprTargetEl expr <$> (keyword "as" *> space1 *> endHead *> colLabel),-                    ImplicitlyAliasedExprTargetEl expr <$> ident-                  ],-              pure (ExprTargetEl expr)-            ],-        AsteriskTargetEl <$ char '*'-      ]--onExpressionsClause = do-  keyword "on"-  space1-  endHead-  inParens (sep1 commaSeparator aExpr)---- * Into clause details---- |--- ==== References--- @--- OptTempTableName:---   | TEMPORARY opt_table qualified_name---   | TEMP opt_table qualified_name---   | LOCAL TEMPORARY opt_table qualified_name---   | LOCAL TEMP opt_table qualified_name---   | GLOBAL TEMPORARY opt_table qualified_name---   | GLOBAL TEMP opt_table qualified_name---   | UNLOGGED opt_table qualified_name---   | TABLE qualified_name---   | qualified_name--- @-optTempTableName =-  asum-    [ do-        a <--          asum-            [ TemporaryOptTempTableName <$ keyword "temporary" <* space1,-              TempOptTempTableName <$ keyword "temp" <* space1,-              LocalTemporaryOptTempTableName <$ keyphrase "local temporary" <* space1,-              LocalTempOptTempTableName <$ keyphrase "local temp" <* space1,-              GlobalTemporaryOptTempTableName <$ keyphrase "global temporary" <* space1,-              GlobalTempOptTempTableName <$ keyphrase "global temp" <* space1,-              UnloggedOptTempTableName <$ keyword "unlogged" <* space1-            ]-        b <- option False (True <$ keyword "table" <* space1)-        c <- qualifiedName-        return (a b c),-      do-        keyword "table"-        space1-        endHead-        TableOptTempTableName <$> qualifiedName,-      QualifedOptTempTableName <$> qualifiedName-    ]---- * Group by details--groupByItem =-  asum-    [ EmptyGroupingSetGroupByItem <$ (char '(' *> space *> char ')'),-      RollupGroupByItem <$> (keyword "rollup" *> endHead *> space *> inParens (sep1 commaSeparator aExpr)),-      CubeGroupByItem <$> (keyword "cube" *> endHead *> space *> inParens (sep1 commaSeparator aExpr)),-      GroupingSetsGroupByItem <$> (keyphrase "grouping sets" *> endHead *> space *> inParens (sep1 commaSeparator groupByItem)),-      ExprGroupByItem <$> aExpr-    ]---- * Window clause details--windowDefinition = WindowDefinition <$> (colId <* space1 <* keyword "as" <* space1 <* endHead) <*> windowSpecification---- |--- ==== References--- @--- window_specification:---   |  '(' opt_existing_window_name opt_partition_clause---             opt_sort_clause opt_frame_clause ')'--- @-windowSpecification =-  inParens-    $ asum-      [ do-          a <- frameClause-          return (WindowSpecification Nothing Nothing Nothing (Just a)),-        do-          a <- sortClause-          b <- optional (space1 *> frameClause)-          return (WindowSpecification Nothing Nothing (Just a) b),-        do-          a <- partitionByClause-          b <- optional (space1 *> sortClause)-          c <- optional (space1 *> frameClause)-          return (WindowSpecification Nothing (Just a) b c),-        do-          a <- colId-          b <- optional (space1 *> partitionByClause)-          c <- optional (space1 *> sortClause)-          d <- optional (space1 *> frameClause)-          return (WindowSpecification (Just a) b c d),-        pure (WindowSpecification Nothing Nothing Nothing Nothing)-      ]--partitionByClause = keyphrase "partition by" *> space1 *> endHead *> sep1 commaSeparator aExpr---- |--- ==== References--- @--- opt_frame_clause:---   |  RANGE frame_extent opt_window_exclusion_clause---   |  ROWS frame_extent opt_window_exclusion_clause---   |  GROUPS frame_extent opt_window_exclusion_clause---   |  EMPTY--- @-frameClause = do-  a <- frameClauseMode <* space1 <* endHead-  b <- frameExtent-  c <- optional (space1 *> windowExclusionClause)-  return (FrameClause a b c)--frameClauseMode =-  asum-    [ RangeFrameClauseMode <$ keyword "range",-      RowsFrameClauseMode <$ keyword "rows",-      GroupsFrameClauseMode <$ keyword "groups"-    ]--frameExtent =-  BetweenFrameExtent <$> (keyword "between" *> space1 *> endHead *> frameBound <* space1 <* keyword "and" <* space1) <*> frameBound-    <|> SingularFrameExtent <$> frameBound---- |--- ==== References--- @---   |  UNBOUNDED PRECEDING---   |  UNBOUNDED FOLLOWING---   |  CURRENT_P ROW---   |  a_expr PRECEDING---   |  a_expr FOLLOWING--- @-frameBound =-  UnboundedPrecedingFrameBound <$ keyphrase "unbounded preceding"-    <|> UnboundedFollowingFrameBound <$ keyphrase "unbounded following"-    <|> CurrentRowFrameBound <$ keyphrase "current row"-    <|> do-      a <- aExpr-      space1-      PrecedingFrameBound a <$ keyword "preceding" <|> FollowingFrameBound a <$ keyword "following"--windowExclusionClause =-  CurrentRowWindowExclusionClause <$ keyphrase "exclude current row"-    <|> GroupWindowExclusionClause <$ keyphrase "exclude group"-    <|> TiesWindowExclusionClause <$ keyphrase "exclude ties"-    <|> NoOthersWindowExclusionClause <$ keyphrase "exclude no others"---- * Table refs--fromList = sep1 commaSeparator tableRef--fromClause = keyword "from" *> endHead *> space1 *> fromList---- |--- >>> testParser tableRef "a left join b on (a.i = b.i)"--- JoinTableRef (MethJoinedTable (QualJoinMeth...-tableRef =-  label "table reference"-    $ do-      tr <- nonTrailingTableRef-      recur tr-  where-    recur tr =-      asum-        [ do-            tr2 <- wrapToHead (space1 *> trailingTableRef tr)-            endHead-            recur tr2,-          pure tr-        ]--nonTrailingTableRef =-  asum-    [ lateralTableRef-        <|> wrapToHead nonLateralTableRef-        <|> relationExprTableRef-        <|> joinedTableWithAliasTableRef-        <|> inParensJoinedTableTableRef-    ]-  where-    relationExprTableRef = do-      relationExpr <- relationExpr-      endHead-      optAliasClause <- optional (space1 *> aliasClause)-      optTablesampleClause <- optional (space1 *> tablesampleClause)-      return (RelationExprTableRef relationExpr optAliasClause optTablesampleClause)--    lateralTableRef = do-      keyword "lateral"-      space1-      endHead-      lateralableTableRef True--    nonLateralTableRef = lateralableTableRef False--    lateralableTableRef lateral =-      asum-        [ do-            a <- funcTable-            b <- optional (space1 *> funcAliasClause)-            return (FuncTableRef lateral a b),-          do-            select <- selectWithParens-            optAliasClause <- optional $ space1 *> aliasClause-            return (SelectTableRef lateral select optAliasClause)-        ]--    inParensJoinedTableTableRef = JoinTableRef <$> inParensJoinedTable <*> pure Nothing--    joinedTableWithAliasTableRef = do-      joinedTable <- wrapToHead (inParens joinedTable)-      space1-      alias <- aliasClause-      return (JoinTableRef joinedTable (Just alias))--trailingTableRef tableRef =-  JoinTableRef <$> trailingJoinedTable tableRef <*> pure Nothing--relationExpr =-  label "relation expression"-    $ asum-      [ do-          keyword "only"-          space1-          name <- qualifiedName-          return (OnlyRelationExpr name False),-        inParensWithClause (keyword "only") qualifiedName <&> \a -> OnlyRelationExpr a True,-        do-          name <- qualifiedName-          asterisk <--            asum-              [ True <$ (space1 *> char '*'),-                pure False-              ]-          return (SimpleRelationExpr name asterisk)-      ]--relationExprOptAlias reservedKeywords = do-  a <- relationExpr-  b <- optional $ do-    space1-    b <- trueIfPresent (keyword "as" *> space1)-    c <- filteredColId reservedKeywords-    return (b, c)-  return (RelationExprOptAlias a b)--tablesampleClause = do-  keyword "tablesample"-  space1-  endHead-  a <- funcName-  space-  b <- inParens exprList-  c <- optional (space *> repeatableClause)-  return (TablesampleClause a b c)--repeatableClause = do-  keyword "repeatable"-  space-  inParens (endHead *> aExpr)--funcTable =-  asum-    [ do-        keyword "rows"-        space1-        keyword "from"-        space-        a <- inParens (endHead *> rowsfromList)-        b <- trueIfPresent (space *> optOrdinality)-        return (RowsFromFuncTable a b),-      do-        a <- funcExprWindowless-        b <- trueIfPresent (space1 *> optOrdinality)-        return (FuncExprFuncTable a b)-    ]--rowsfromItem = do-  a <- funcExprWindowless-  endHead-  b <- optional (space1 *> colDefList)-  return (RowsfromItem a b)--rowsfromList = sep1 commaSeparator rowsfromItem--colDefList = keyword "as" *> space *> inParens (endHead *> tableFuncElementList)--optOrdinality = keyword "with" *> space1 *> keyword "ordinality"--tableFuncElementList = sep1 commaSeparator tableFuncElement--tableFuncElement = do-  a <- wrapToHead colId-  space1-  b <- typename-  c <- optional (space1 *> collateClause)-  return (TableFuncElement a b c)--collateClause = keyword "collate" *> space1 *> endHead *> anyName--funcAliasClause =-  asum-    [ do-        _ <- keyword "as"-        asum-          [ do-              space-              inParens $ do-                endHead-                AsFuncAliasClause <$> tableFuncElementList,-            do-              space1-              a <- colId-              asum-                [ do-                    space-                    inParens $ do-                      endHead-                      asum-                        [ AsColIdFuncAliasClause a <$> wrapToHead tableFuncElementList,-                          AliasFuncAliasClause <$> AliasClause True a <$> Just <$> nameList-                        ],-                  pure (AliasFuncAliasClause (AliasClause True a Nothing))-                ]-          ],-      do-        a <- colId-        asum-          [ do-              space-              inParens $ do-                endHead-                asum-                  [ ColIdFuncAliasClause a <$> wrapToHead tableFuncElementList,-                    AliasFuncAliasClause <$> AliasClause False a <$> Just <$> nameList-                  ],-            pure (AliasFuncAliasClause (AliasClause False a Nothing))-          ]-    ]--joinedTable =-  head >>= tail-  where-    head =-      asum-        [ do-            tr <- wrapToHead nonTrailingTableRef-            space1-            trailingJoinedTable tr,-          inParensJoinedTable-        ]-    tail jt =-      asum-        [ do-            jt2 <- wrapToHead (space1 *> trailingJoinedTable (JoinTableRef jt Nothing))-            endHead-            tail jt2,-          pure jt-        ]---- |--- ==== References--- @---   | '(' joined_table ')'--- @-inParensJoinedTable = InParensJoinedTable <$> inParens joinedTable---- |--- ==== References--- @---   | table_ref CROSS JOIN table_ref---   | table_ref join_type JOIN table_ref join_qual---   | table_ref JOIN table_ref join_qual---   | table_ref NATURAL join_type JOIN table_ref---   | table_ref NATURAL JOIN table_ref--- @-trailingJoinedTable tr1 =-  asum-    [ do-        keyphrase "cross join"-        endHead-        space1-        tr2 <- nonTrailingTableRef-        return (MethJoinedTable CrossJoinMeth tr1 tr2),-      do-        jt <- joinTypedJoin-        endHead-        space1-        tr2 <- tableRef-        space1-        jq <- joinQual-        return (MethJoinedTable (QualJoinMeth jt jq) tr1 tr2),-      do-        keyword "natural"-        endHead-        space1-        jt <- joinTypedJoin-        space1-        tr2 <- nonTrailingTableRef-        return (MethJoinedTable (NaturalJoinMeth jt) tr1 tr2)-    ]-  where-    joinTypedJoin =-      Just <$> (joinType <* endHead <* space1 <* keyword "join")-        <|> Nothing <$ keyword "join"--joinType =-  asum-    [ do-        keyword "full"-        endHead-        outer <- outerAfterSpace-        return (FullJoinType outer),-      do-        keyword "left"-        endHead-        outer <- outerAfterSpace-        return (LeftJoinType outer),-      do-        keyword "right"-        endHead-        outer <- outerAfterSpace-        return (RightJoinType outer),-      keyword "inner" $> InnerJoinType-    ]-  where-    outerAfterSpace = (space1 *> keyword "outer") $> True <|> pure False--joinQual =-  asum-    [ keyword "using" *> space1 *> inParens (sep1 commaSeparator colId) <&> UsingJoinQual,-      keyword "on" *> space1 *> aExpr <&> OnJoinQual-    ]--aliasClause = do-  (as, alias) <- (True,) <$> (keyword "as" *> space1 *> endHead *> colId) <|> (False,) <$> colId-  columnAliases <- optional (space1 *> inParens (sep1 commaSeparator colId))-  return (AliasClause as alias columnAliases)---- * Where--whereClause = keyword "where" *> space1 *> endHead *> aExpr--whereOrCurrentClause = do-  keyword "where"-  space1-  endHead-  asum-    [ do-        keyword "current"-        space1-        keyword "of"-        space1-        endHead-        a <- cursorName-        return (CursorWhereOrCurrentClause a),-      ExprWhereOrCurrentClause <$> aExpr-    ]---- * Sorting--sortClause = do-  keyphrase "order by"-  endHead-  space1-  a <- sep1 commaSeparator sortBy-  return a--sortBy = do-  a <- filteredAExpr ["using", "asc", "desc", "nulls"]-  asum-    [ do-        space1-        keyword "using"-        space1-        endHead-        b <- qualAllOp-        c <- optional (space1 *> nullsOrder)-        return (UsingSortBy a b c),-      do-        b <- optional (space1 *> ascDesc)-        c <- optional (space1 *> nullsOrder)-        return (AscDescSortBy a b c)-    ]---- * Expressions--exprList = sep1 commaSeparator aExpr--exprListInParens = inParens exprList---- |--- Notice that the tree constructed by this parser does not reflect--- the precedence order of Postgres.--- For the purposes of this library it simply doesn't matter,--- so we're not bothering with that.------ ==== Composite on the right:------ >>> testParser aExpr "a = b :: int4"--- SymbolicBinOpAExpr (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "a") Nothing))) (MathSymbolicExprBinOp EqualsMathOp) (TypecastAExpr (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "b") Nothing))) (Typename False (GenericTypeSimpleTypename (GenericType (UnquotedIdent "int4") Nothing Nothing)) False Nothing))------ ==== Composite on the left:------ >>> testParser aExpr "a = b :: int4 and c"--- SymbolicBinOpAExpr (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "a") Nothing))) (MathSymbolicExprBinOp EqualsMathOp) (AndAExpr (TypecastAExpr (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "b") Nothing))) (Typename False (GenericTypeSimpleTypename (GenericType (UnquotedIdent "int4") Nothing Nothing)) False Nothing)) (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "c") Nothing))))-aExpr = customizedAExpr cExpr--filteredAExpr = customizedAExpr . customizedCExpr . filteredColumnref--customizedAExpr cExpr = suffixRec base suffix-  where-    aExpr = customizedAExpr cExpr-    base =-      asum-        [ DefaultAExpr <$ keyword "default",-          UniqueAExpr <$> (keyword "unique" *> space1 *> selectWithParens),-          qualOpExpr aExpr PrefixQualOpAExpr,-          PlusAExpr <$> plusedExpr aExpr,-          MinusAExpr <$> minusedExpr aExpr,-          NotAExpr <$> (keyword "not" *> space1 *> aExpr),-          CExprAExpr <$> cExpr-        ]-    suffix a =-      asum-        [ overlapsSuffix a,-          do-            space1-            b <- wrapToHead subqueryOp-            space1-            c <- wrapToHead subType-            space-            d <- Left <$> wrapToHead selectWithParens <|> Right <$> inParens aExpr-            return (SubqueryAExpr a b c d),-          typecastExpr a TypecastAExpr,-          CollateAExpr a <$> (space1 *> keyword "collate" *> space1 *> endHead *> anyName),-          AtTimeZoneAExpr a <$> (space1 *> keyphrase "at time zone" *> space1 *> endHead *> aExpr),-          symbolicBinOpExpr a aExpr SymbolicBinOpAExpr,-          SuffixQualOpAExpr a <$> (space *> qualOp),-          AndAExpr a <$> (space1 *> keyword "and" *> space1 *> endHead *> aExpr),-          OrAExpr a <$> (space1 *> keyword "or" *> space1 *> endHead *> aExpr),-          do-            space1-            b <- trueIfPresent (keyword "not" *> space1)-            c <--              asum-                [ LikeVerbalExprBinOp <$ keyword "like",-                  IlikeVerbalExprBinOp <$ keyword "ilike",-                  SimilarToVerbalExprBinOp <$ keyphrase "similar to"-                ]-            space1-            endHead-            d <- aExpr-            e <- optional (space1 *> keyword "escape" *> space1 *> endHead *> aExpr)-            return (VerbalExprBinOpAExpr a b c d e),-          do-            space1-            keyword "is"-            space1-            endHead-            b <- trueIfPresent (keyword "not" *> space1)-            c <--              asum-                [ NullAExprReversableOp <$ keyword "null",-                  TrueAExprReversableOp <$ keyword "true",-                  FalseAExprReversableOp <$ keyword "false",-                  UnknownAExprReversableOp <$ keyword "unknown",-                  DistinctFromAExprReversableOp <$> (keyword "distinct" *> space1 *> keyword "from" *> space1 *> endHead *> aExpr),-                  OfAExprReversableOp <$> (keyword "of" *> space1 *> endHead *> inParens typeList),-                  DocumentAExprReversableOp <$ keyword "document"-                ]-            return (ReversableOpAExpr a b c),-          do-            space1-            b <- trueIfPresent (keyword "not" *> space1)-            keyword "between"-            space1-            endHead-            c <--              asum-                [ BetweenSymmetricAExprReversableOp <$ (keyword "symmetric" *> space1),-                  BetweenAExprReversableOp True <$ (keyword "asymmetric" *> space1),-                  pure (BetweenAExprReversableOp False)-                ]-            d <- bExpr-            space1-            keyword "and"-            space1-            e <- aExpr-            return (ReversableOpAExpr a b (c d e)),-          do-            space1-            b <- trueIfPresent (keyword "not" *> space1)-            keyword "in"-            space-            c <- InAExprReversableOp <$> inExpr-            return (ReversableOpAExpr a b c),-          IsnullAExpr a <$ (space1 *> keyword "isnull"),-          NotnullAExpr a <$ (space1 *> keyword "notnull")-        ]---- |--- The @OVERLAPS@ operator, as a suffix of an already parsed left operand.------ @gram.y@ specifies it as @row OVERLAPS row@, and the straightforward--- transcription of that is to parse a @row@ speculatively in the base position--- of 'customizedAExpr'. That is what this parser replaces, and the reason it--- exists: a speculative @row@ parse consumes and then discards a whole--- parenthesised group, so every group in the input got parsed once for--- @OVERLAPS@ and again for the alternative that actually matched — one of the--- factors that made parsing exponential in nesting depth.------ Instead we let the ordinary base parser consume the left operand exactly--- once and reinterpret its result here. The two 'CExpr' shapes below are--- precisely the two 'Row' shapes, so no input that used to parse stops--- parsing, and the constructed tree is identical.------ >>> testParser aExpr "(1, 2) overlaps (3, 4)"--- OverlapsAExpr (ImplicitRowRow (ImplicitRow (CExprAExpr (AexprConstCExpr (IAexprConst 1)) :| []) (CExprAExpr (AexprConstCExpr (IAexprConst 2))))) (ImplicitRowRow (ImplicitRow (CExprAExpr (AexprConstCExpr (IAexprConst 3)) :| []) (CExprAExpr (AexprConstCExpr (IAexprConst 4)))))-overlapsSuffix :: AExpr -> Parser AExpr-overlapsSuffix a = do-  b <- maybe empty pure (aExprRow a)-  space1-  keyword "overlaps"-  endHead-  space1-  c <- row-  return (OverlapsAExpr b c)-  where-    aExprRow = \case-      CExprAExpr (ExplicitRowCExpr x) -> Just (ExplicitRowRow x)-      CExprAExpr (ImplicitRowCExpr x) -> Just (ImplicitRowRow x)-      _ -> Nothing--bExpr = customizedBExpr cExpr--customizedBExpr cExpr = suffixRec base suffix-  where-    bExpr = customizedBExpr cExpr-    base =-      asum-        [ qualOpExpr bExpr QualOpBExpr,-          PlusBExpr <$> plusedExpr bExpr,-          MinusBExpr <$> minusedExpr bExpr,-          CExprBExpr <$> cExpr-        ]-    suffix a =-      asum-        [ typecastExpr a TypecastBExpr,-          symbolicBinOpExpr a bExpr SymbolicBinOpBExpr,-          do-            space1-            keyword "is"-            space1-            endHead-            b <- trueIfPresent (keyword "not" *> space1)-            c <--              asum-                [ DistinctFromBExprIsOp <$> (keyphrase "distinct from" *> space1 *> endHead *> bExpr),-                  OfBExprIsOp <$> (keyword "of" *> space1 *> endHead *> inParens typeList),-                  DocumentBExprIsOp <$ keyword "document"-                ]-            return (IsOpBExpr a b c)-        ]--cExpr = customizedCExpr columnref--customizedCExpr columnref =-  asum-    [ ParamCExpr <$> (char '$' *> decimal <* endHead) <*> optional (space *> indirection),-      CaseCExpr <$> caseExpr,-      ExplicitRowCExpr <$> explicitRow,-      inParensWithClause (keyword "grouping") (GroupingCExpr <$> sep1 commaSeparator aExpr),-      keyword "exists" *> space *> (ExistsCExpr <$> selectWithParens),-      do-        keyword "array"-        space-        join-          $ asum-            [ fmap (fmap (ArrayCExpr . Right)) arrayExprCont,-              fmap (fmap (ArrayCExpr . Left) . pure) selectWithParens-            ],-      do-        a <- wrapToHead selectWithParens-        endHead-        b <- optional (space *> indirection)-        return (SelectWithParensCExpr a b),-      parenthesizedExprCExpr,-      AexprConstCExpr <$> wrapToHead aexprConst,-      FuncCExpr <$> funcExpr,-      ColumnrefCExpr <$> columnref-    ]---- |--- The two @cExpr@ forms that consist of an expression in parentheses:--- a parenthesised expression (@InParensCExpr@) and an implicit row--- (@ImplicitRowCExpr@).------ They are parsed together, and deliberately so. Written as two alternatives--- of the surrounding 'asum' — which is how they used to be written — the--- implicit-row alternative parses the whole first expression of the group--- before it can discover that no comma follows, and then the parenthesised---- expression alternative parses that same text over again. Nest that and the--- work doubles per level. Sharing the single @aExpr@ parse between the two and--- deciding on the character that follows it removes the duplication, which is--- what makes parsing linear rather than exponential in nesting depth.------ The @(@ is not committed to with 'endHead' here: 'selectWithParens' is tried--- before this parser and other parenthesised forms exist elsewhere in the--- grammar, so the group must stay backtrackable. Commitment happens on the--- comma or the closing paren, once the form is unambiguous.------ >>> testParser cExpr "(a + b)"--- InParensCExpr (SymbolicBinOpAExpr (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "a") Nothing))) (MathSymbolicExprBinOp PlusMathOp) (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "b") Nothing)))) Nothing------ >>> testParser cExpr "(a, b)"--- ImplicitRowCExpr (ImplicitRow (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "a") Nothing)) :| []) (CExprAExpr (ColumnrefCExpr (Columnref (UnquotedIdent "b") Nothing))))-parenthesizedExprCExpr :: Parser CExpr-parenthesizedExprCExpr = do-  char '('-  space-  a <- aExpr-  space-  asum-    [ do-        char ','-        endHead-        space-        b <- exprList-        space-        char ')'-        return $ ImplicitRowCExpr $ case NonEmpty.consAndUnsnoc a b of-          (c, d) -> ImplicitRow c d,-      do-        char ')'-        endHead-        b <- optional (space *> indirection)-        return (InParensCExpr a b)-    ]--subqueryOp =-  asum-    [ AnySubqueryOp <$> (keyword "operator" *> space *> endHead *> inParens anyOperator),-      do-        a <- trueIfPresent (keyword "not" *> space1)-        LikeSubqueryOp a <$ keyword "like" <|> IlikeSubqueryOp a <$ keyword "ilike",-      AllSubqueryOp <$> allOp-    ]--subType =-  asum-    [ AnySubType <$ keyword "any",-      SomeSubType <$ keyword "some",-      AllSubType <$ keyword "all"-    ]--inExpr =-  (ExprListInExpr <$> parse (Megaparsec.try (toParsec (inParens exprList))))-    <|> (SelectInExpr <$> wrapToHead selectWithParens)--symbolicBinOpExpr a bParser constr = do-  binOp <- label "binary operator" (space *> wrapToHead symbolicExprBinOp <* space)-  b <- bParser-  return (constr a binOp b)--typecastExpr :: a -> (a -> Typename -> a) -> HeadedParsec Void Text a-typecastExpr prefix constr = do-  space-  string "::"-  endHead-  space-  type' <- typename-  return (constr prefix type')--plusedExpr expr = char '+' *> space *> expr--minusedExpr expr = char '-' *> space *> expr--qualOpExpr expr constr = constr <$> wrapToHead qualOp <*> (space *> expr)--row = ExplicitRowRow <$> explicitRow <|> ImplicitRowRow <$> implicitRow--explicitRow = keyword "row" *> space *> inParens (optional exprList)--implicitRow = inParens $ do-  a <- wrapToHead aExpr-  commaSeparator-  b <- exprList-  return $ case NonEmpty.consAndUnsnoc a b of-    (c, d) -> ImplicitRow c d--arrayExprCont =-  inBracketsCont-    $ asum-      [ ArrayExprListArrayExpr <$> sep1 commaSeparator (join arrayExprCont),-        ExprListArrayExpr <$> exprList,-        pure EmptyArrayExpr-      ]--caseExpr = label "case expression" $ do-  keyword "case"-  space1-  endHead-  arg <- optional (aExpr <* space1)-  whenClauses <- sep1 space1 whenClause-  space1-  default' <- optional elseClause-  keyword "end"-  pure $ CaseExpr arg whenClauses default'--whenClause = do-  keyword "when"-  space1-  endHead-  a <- aExpr-  space1-  keyword "then"-  space1-  b <- aExpr-  return (WhenClause a b)--elseClause = do-  keyword "else"-  space1-  endHead-  a <- aExpr-  space1-  return a--funcExpr =-  asum-    [ SubexprFuncExpr <$> funcExprCommonSubexpr,-      do-        a <- funcApplication-        endHead-        b <- optional (space1 *> withinGroupClause)-        c <- optional (space1 *> filterClause)-        d <- optional (space1 *> overClause)-        return (ApplicationFuncExpr a b c d)-    ]--funcExprWindowless =-  asum-    [ CommonSubexprFuncExprWindowless <$> funcExprCommonSubexpr,-      ApplicationFuncExprWindowless <$> funcApplication-    ]--withinGroupClause = do-  keyphrase "within group"-  endHead-  space-  inParens sortClause--filterClause = do-  keyword "filter"-  endHead-  space-  inParens (keyword "where" *> space1 *> aExpr)--overClause = do-  keyword "over"-  space1-  endHead-  asum-    [ WindowOverClause <$> windowSpecification,-      ColIdOverClause <$> colId-    ]--funcExprCommonSubexpr =-  asum-    [ CollationForFuncExprCommonSubexpr <$> (inParensWithClause (keyphrase "collation for") aExpr),-      CurrentDateFuncExprCommonSubexpr <$ keyword "current_date",-      CurrentTimestampFuncExprCommonSubexpr <$> labeledIconst "current_timestamp",-      CurrentTimeFuncExprCommonSubexpr <$> labeledIconst "current_time",-      LocalTimestampFuncExprCommonSubexpr <$> labeledIconst "localtimestamp",-      LocalTimeFuncExprCommonSubexpr <$> labeledIconst "localtime",-      CurrentRoleFuncExprCommonSubexpr <$ keyword "current_role",-      CurrentUserFuncExprCommonSubexpr <$ keyword "current_user",-      SessionUserFuncExprCommonSubexpr <$ keyword "session_user",-      UserFuncExprCommonSubexpr <$ keyword "user",-      CurrentCatalogFuncExprCommonSubexpr <$ keyword "current_catalog",-      CurrentSchemaFuncExprCommonSubexpr <$ keyword "current_schema",-      inParensWithClause (keyword "cast") (CastFuncExprCommonSubexpr <$> aExpr <*> (space1 *> keyword "as" *> space1 *> typename)),-      inParensWithClause (keyword "extract") (ExtractFuncExprCommonSubexpr <$> optional extractList),-      inParensWithClause (keyword "overlay") (OverlayFuncExprCommonSubexpr <$> overlayList),-      inParensWithClause (keyword "position") (PositionFuncExprCommonSubexpr <$> optional positionList),-      inParensWithClause (keyword "substring") (SubstringFuncExprCommonSubexpr <$> optional substrList),-      inParensWithClause (keyword "treat") (TreatFuncExprCommonSubexpr <$> aExpr <*> (space1 *> keyword "as" *> space1 *> typename)),-      inParensWithClause (keyword "trim") (TrimFuncExprCommonSubexpr <$> optional (trimModifier <* space1) <*> trimList),-      inParensWithClause (keyword "nullif") (NullIfFuncExprCommonSubexpr <$> aExpr <*> (commaSeparator *> aExpr)),-      inParensWithClause (keyword "coalesce") (CoalesceFuncExprCommonSubexpr <$> exprList),-      inParensWithClause (keyword "greatest") (GreatestFuncExprCommonSubexpr <$> exprList),-      inParensWithClause (keyword "least") (LeastFuncExprCommonSubexpr <$> exprList)-    ]-  where-    labeledIconst label = keyword label *> endHead *> optional (space *> inParens iconst)--extractList = ExtractList <$> extractArg <*> (space1 *> keyword "from" *> space1 *> aExpr)--extractArg =-  asum-    [ YearExtractArg <$ keyword "year",-      MonthExtractArg <$ keyword "month",-      DayExtractArg <$ keyword "day",-      HourExtractArg <$ keyword "hour",-      MinuteExtractArg <$ keyword "minute",-      SecondExtractArg <$ keyword "second",-      SconstExtractArg <$> sconst,-      IdentExtractArg <$> ident-    ]--overlayList = do-  a <- aExpr-  space1-  b <- overlayPlacing-  space1-  c <- substrFrom-  d <- optional (space1 *> substrFor)-  return (OverlayList a b c d)--overlayPlacing = keyword "placing" *> space1 *> endHead *> aExpr--positionList = PositionList <$> bExpr <*> (space1 *> keyword "in" *> space1 *> bExpr)--substrList =-  asum-    [ ExprSubstrList <$> wrapToHead aExpr <*> (space1 *> substrListFromFor),-      ExprListSubstrList <$> exprList-    ]--substrListFromFor =-  asum-    [ do-        a <- substrFrom-        asum-          [ do-              b <- space1 *> substrFor-              return (FromForSubstrListFromFor a b),-            return (FromSubstrListFromFor a)-          ],-      do-        a <- substrFor-        asum-          [ do-              b <- space1 *> substrFrom-              return (ForFromSubstrListFromFor a b),-            return (ForSubstrListFromFor a)-          ]-    ]--substrFrom = keyword "from" *> space1 *> endHead *> aExpr--substrFor = keyword "for" *> space1 *> endHead *> aExpr--trimModifier =-  BothTrimModifier <$ keyword "both"-    <|> LeadingTrimModifier <$ keyword "leading"-    <|> TrailingTrimModifier <$ keyword "trailing"--trimList =-  asum-    [ ExprFromExprListTrimList <$> wrapToHead aExpr <*> (space1 *> keyword "from" *> space1 *> endHead *> exprList),-      FromExprListTrimList <$> (keyword "from" *> space1 *> endHead *> exprList),-      ExprListTrimList <$> exprList-    ]---- |--- \"operator\" immediately followed by \"(\" is always parsed as the start--- of a qualified operator (@OPERATOR(...)@), never as a call to a function--- literally named \"operator\", mirroring how real PostgreSQL's grammar--- resolves the conflict between these two productions in favor of qual_op.-funcApplication =-  notFollowedBy (keyword "operator" *> space *> char '(')-    *> inParensWithLabel FuncApplication funcName (optional funcApplicationParams)--funcApplicationParams =-  asum-    [ starFuncApplicationParams,-      listVariadicFuncApplicationParams,-      singleVariadicFuncApplicationParams,-      normalFuncApplicationParams-    ]--normalFuncApplicationParams = do-  optAllOrDistinct <- optional (allOrDistinct <* space1)-  argList <- sep1 commaSeparator funcArgExpr-  endHead-  optSortClause <- optional (space1 *> sortClause)-  return (NormalFuncApplicationParams optAllOrDistinct argList optSortClause)--singleVariadicFuncApplicationParams = do-  keyword "variadic"-  space1-  endHead-  arg <- funcArgExpr-  optSortClause <- optional (space1 *> sortClause)-  return (VariadicFuncApplicationParams Nothing arg optSortClause)--listVariadicFuncApplicationParams = do-  (argList, _) <- wrapToHead $ sepEnd1 commaSeparator (keyword "variadic" <* space1) funcArgExpr-  endHead-  arg <- funcArgExpr-  optSortClause <- optional (space1 *> sortClause)-  return (VariadicFuncApplicationParams (Just argList) arg optSortClause)--starFuncApplicationParams = space *> char '*' *> endHead *> space $> StarFuncApplicationParams---- |--- ==== References--- @--- func_arg_expr:---   | a_expr---   | param_name COLON_EQUALS a_expr---   | param_name EQUALS_GREATER a_expr--- param_name:---   | type_function_name--- @-funcArgExpr =-  asum-    [ do-        a <- wrapToHead typeFunctionName-        space-        asum-          [ do-              string ":="-              endHead-              b <- space *> aExpr-              return (ColonEqualsFuncArgExpr a b),-            do-              string "=>"-              endHead-              b <- space *> aExpr-              return (EqualsGreaterFuncArgExpr a b)-          ],-      ExprFuncArgExpr <$> aExpr-    ]---- * Ops--symbolicExprBinOp =-  QualSymbolicExprBinOp <$> qualOp-    <|> MathSymbolicExprBinOp <$> mathOp--lexicalExprBinOp = asum $ fmap keyphrase $ ["and", "or", "is distinct from", "is not distinct from"]--qualOp =-  asum-    [ OpQualOp <$> op,-      OperatorQualOp <$> inParensWithClause (keyword "operator") anyOperator-    ]--qualAllOp =-  asum-    [ AnyQualAllOp <$> (keyword "operator" *> space *> inParens (endHead *> anyOperator)),-      AllQualAllOp <$> allOp-    ]--op = do-  a <- takeWhile1P Nothing Predicate.opChar-  case Validation.op a of-    Nothing -> return a-    Just err -> fail (Text.unpack err)--anyOperator =-  asum-    [ AllOpAnyOperator <$> allOp,-      QualifiedAnyOperator <$> colId <*> (space *> char '.' *> space *> anyOperator)-    ]--allOp =-  asum-    [ OpAllOp <$> op,-      MathAllOp <$> mathOp-    ]--mathOp =-  asum-    [ ArrowLeftArrowRightMathOp <$ string' "<>",-      GreaterEqualsMathOp <$ string' ">=",-      ExclamationEqualsMathOp <$ string' "!=",-      LessEqualsMathOp <$ string' "<=",-      PlusMathOp <$ char '+',-      MinusMathOp <$ char '-',-      AsteriskMathOp <$ char '*',-      SlashMathOp <$ char '/',-      PercentMathOp <$ char '%',-      ArrowUpMathOp <$ char '^',-      ArrowLeftMathOp <$ char '<',-      ArrowRightMathOp <$ char '>',-      EqualsMathOp <$ char '='-    ]---- * Constants---- |--- >>> testParser aexprConst "32948023849023"--- IAexprConst 32948023849023------ >>> testParser aexprConst "'abc''de'"--- SAexprConst "abc'de"------ >>> testParser aexprConst "23.43234"--- FAexprConst 23.43234------ >>> testParser aexprConst "32423423.324324872"--- FAexprConst 3.2423423324324872e7------ >>> testParser aexprConst "NULL"--- NullAexprConst------ ==== References--- @--- AexprConst: Iconst---       | FCONST---       | Sconst---       | BCONST---       | XCONST---       | func_name Sconst---       | func_name '(' func_arg_list opt_sort_clause ')' Sconst---       | ConstTypename Sconst---       | ConstInterval Sconst opt_interval---       | ConstInterval '(' Iconst ')' Sconst---       | TRUE_P---       | FALSE_P---       | NULL_P--- @-aexprConst =-  asum-    [ do-        keyword "interval"-        space1-        endHead-        a <--          asum-            [ do-                a <- sconst-                endHead-                b <- optional (space1 *> interval)-                return (StringIntervalAexprConst a b),-              do-                a <- inParens iconst-                space1-                endHead-                b <- sconst-                return (IntIntervalAexprConst a b)-            ]-        return a,-      do-        a <- constTypename-        space1-        endHead-        b <- sconst-        return (ConstTypenameAexprConst a b),-      BoolAexprConst True <$ keyword "true",-      BoolAexprConst False <$ keyword "false",-      NullAexprConst <$ keyword "null" <* parse (Megaparsec.notFollowedBy MegaparsecChar.alphaNumChar),-      either IAexprConst FAexprConst <$> iconstOrFconst,-      SAexprConst <$> sconst,-      label "bit literal" $ do-        string' "b'"-        endHead-        a <- takeWhile1P (Just "0 or 1") (\b -> b == '0' || b == '1')-        char '\''-        return (BAexprConst a),-      label "hex literal" $ do-        string' "x'"-        endHead-        a <- takeWhile1P (Just "Hex digit") Predicate.hexDigit-        char '\''-        return (XAexprConst a),-      wrapToHead $ do-        a <- funcName-        space-        char '('-        space-        b <- sep1 commaSeparator funcArgExpr-        c <- optional (space1 *> sortClause)-        space-        char ')'-        space1-        d <- sconst-        return (FuncAexprConst a (Just (FuncConstArgs b c)) d),-      FuncAexprConst <$> (wrapToHead funcName <* space1) <*> pure Nothing <*> sconst-    ]--iconstOrFconst = Right <$> fconst <|> Left <$> iconst--iconst = decimal--fconst = float--sconst = quotedString '\'' <|> dollarQuotedSconst--constTypename =-  asum-    [ NumericConstTypename <$> numeric,-      ConstBitConstTypename <$> constBit,-      ConstCharacterConstTypename <$> constCharacter,-      ConstDatetimeConstTypename <$> constDatetime-    ]--numeric =-  asum-    [ IntegerNumeric <$ keyword "integer",-      IntNumeric <$ keyword "int",-      SmallintNumeric <$ keyword "smallint",-      BigintNumeric <$ keyword "bigint",-      RealNumeric <$ keyword "real",-      FloatNumeric <$> (keyword "float" *> endHead *> optional (space *> inParens iconst)),-      DoublePrecisionNumeric <$ keyphrase "double precision",-      DecimalNumeric <$> (keyword "decimal" *> endHead *> optional (space *> exprListInParens)),-      DecNumeric <$> (keyword "dec" *> endHead *> optional (space *> exprListInParens)),-      NumericNumeric <$> (keyword "numeric" *> endHead *> optional (space *> exprListInParens)),-      BooleanNumeric <$ keyword "boolean"-    ]--bit = do-  keyword "bit"-  a <- option False (True <$ space1 <* keyword "varying")-  b <- optional (space1 *> exprListInParens)-  return (Bit a b)--constBit = bit--constCharacter = ConstCharacter <$> (character <* endHead) <*> optional (space *> inParens iconst)--character =-  asum-    [ CharacterCharacter <$> (keyword "character" *> optVaryingAfterSpace),-      CharCharacter <$> (keyword "char" *> optVaryingAfterSpace),-      VarcharCharacter <$ keyword "varchar",-      NationalCharacterCharacter <$> (keyphrase "national character" *> optVaryingAfterSpace),-      NationalCharCharacter <$> (keyphrase "national char" *> optVaryingAfterSpace),-      NcharCharacter <$> (keyword "nchar" *> optVaryingAfterSpace)-    ]-  where-    optVaryingAfterSpace = True <$ space1 <* keyword "varying" <|> pure False---- |--- ==== References--- @--- ConstDatetime:---   | TIMESTAMP '(' Iconst ')' opt_timezone---   | TIMESTAMP opt_timezone---   | TIME '(' Iconst ')' opt_timezone---   | TIME opt_timezone--- @-constDatetime =-  asum-    [ do-        keyword "timestamp"-        a <- optional (space1 *> inParens iconst)-        b <- optional (space1 *> timezone)-        return (TimestampConstDatetime a b),-      do-        keyword "time"-        a <- optional (space1 *> inParens iconst)-        b <- optional (space1 *> timezone)-        return (TimeConstDatetime a b)-    ]--timezone =-  asum-    [ False <$ keyphrase "with time zone",-      True <$ keyphrase "without time zone"-    ]--interval =-  asum-    [ YearToMonthInterval <$ keyphrase "year to month",-      DayToHourInterval <$ keyphrase "day to hour",-      DayToMinuteInterval <$ keyphrase "day to minute",-      DayToSecondInterval <$> (keyphrase "day to" *> space1 *> endHead *> intervalSecond),-      HourToMinuteInterval <$ keyphrase "hour to minute",-      HourToSecondInterval <$> (keyphrase "hour to" *> space1 *> endHead *> intervalSecond),-      MinuteToSecondInterval <$> (keyphrase "minute to" *> space1 *> endHead *> intervalSecond),-      YearInterval <$ keyword "year",-      MonthInterval <$ keyword "month",-      DayInterval <$ keyword "day",-      HourInterval <$ keyword "hour",-      MinuteInterval <$ keyword "minute",-      SecondInterval <$> intervalSecond-    ]--intervalSecond = do-  keyword "second"-  a <- optional (space *> inParens iconst)-  return a---- * Clauses---- |--- ==== References--- @--- select_limit:---   | limit_clause offset_clause---   | offset_clause limit_clause---   | limit_clause---   | offset_clause--- @-selectLimit =-  asum-    [ do-        a <- limitClause-        LimitOffsetSelectLimit a <$> (space1 *> offsetClause) <|> pure (LimitSelectLimit a),-      do-        a <- offsetClause-        OffsetLimitSelectLimit a <$> (space1 *> limitClause) <|> pure (OffsetSelectLimit a)-    ]---- |--- ==== References--- @--- limit_clause:---   | LIMIT select_limit_value---   | LIMIT select_limit_value ',' select_offset_value---   | FETCH first_or_next select_fetch_first_value row_or_rows ONLY---   | FETCH first_or_next row_or_rows ONLY--- @-limitClause =-  ( do-      keyword "limit"-      endHead-      space1-      a <- selectLimitValue-      b <- optional $ do-        commaSeparator-        aExpr-      return (LimitLimitClause a b)-  )-    <|> ( do-            keyword "fetch"-            endHead-            space1-            a <- firstOrNext-            space1-            asum-              [ do-                  b <- rowOrRows-                  space1-                  keyword "only"-                  return (FetchOnlyLimitClause a Nothing b),-                do-                  b <- selectFetchFirstValue-                  space1-                  c <- rowOrRows-                  space1-                  keyword "only"-                  return (FetchOnlyLimitClause a (Just b) c)-              ]-        )--offsetClause = do-  keyword "offset"-  endHead-  space1-  offsetClauseParams--offsetClauseParams =-  FetchFirstOffsetClause <$> wrapToHead selectFetchFirstValue <*> (space1 *> rowOrRows)-    <|> ExprOffsetClause <$> aExpr---- |--- ==== References--- @--- select_limit_value:---   | a_expr---   | ALL--- @-selectLimitValue =-  AllSelectLimitValue <$ keyword "all"-    <|> ExprSelectLimitValue <$> aExpr--rowOrRows =-  True <$ keyword "rows"-    <|> False <$ keyword "row"--firstOrNext =-  False <$ keyword "first"-    <|> True <$ keyword "next"--selectFetchFirstValue =-  ExprSelectFetchFirstValue <$> cExpr-    <|> NumSelectFetchFirstValue <$> (plusOrMinus <* endHead <* space) <*> iconstOrFconst--plusOrMinus = False <$ char '+' <|> True <$ char '-'---- * For Locking---- |--- ==== References--- @--- for_locking_clause:---   | for_locking_items---   | FOR READ ONLY--- for_locking_items:---   | for_locking_item---   | for_locking_items for_locking_item--- @-forLockingClause = readOnly <|> items-  where-    readOnly = ReadOnlyForLockingClause <$ keyphrase "for read only"-    items = ItemsForLockingClause <$> sep1 space1 forLockingItem---- |--- ==== References--- @--- for_locking_item:---   | for_locking_strength locked_rels_list opt_nowait_or_skip--- locked_rels_list:---   | OF qualified_name_list---   | EMPTY--- opt_nowait_or_skip:---   | NOWAIT---   | SKIP LOCKED---   | EMPTY--- @-forLockingItem = do-  strength <- forLockingStrength-  rels <- optional $ space1 *> keyword "of" *> space1 *> endHead *> sep1 commaSeparator qualifiedName-  nowaitOrSkip <- optional (space1 *> nowaitOrSkip)-  return (ForLockingItem strength rels nowaitOrSkip)---- |--- ==== References--- @--- for_locking_strength:---   | FOR UPDATE---   | FOR NO KEY UPDATE---   | FOR SHARE---   | FOR KEY SHARE--- @-forLockingStrength =-  UpdateForLockingStrength <$ keyphrase "for update"-    <|> NoKeyUpdateForLockingStrength <$ keyphrase "for no key update"-    <|> ShareForLockingStrength <$ keyphrase "for share"-    <|> KeyForLockingStrength <$ keyphrase "for key share"--nowaitOrSkip = False <$ keyword "nowait" <|> True <$ keyphrase "skip locked"---- * References & Names--quotedName = filter (const "Empty name") (not . Text.null) (quotedString '"') & fmap QuotedIdent---- |--- ==== References--- @--- ident_start   [A-Za-z\200-\377_]--- ident_cont    [A-Za-z\200-\377_0-9\$]--- identifier    {ident_start}{ident_cont}*--- @-ident = quotedName <|> keywordNameByPredicate (not . Predicate.keyword)---- |--- ==== References--- @--- ColId:---   |  IDENT---   |  unreserved_keyword---   |  col_name_keyword--- @-{-# NOINLINE colId #-}-colId =-  label "identifier"-    $ ident-    <|> keywordNameFromSet (KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword)--{-# NOINLINE filteredColId #-}-filteredColId =-  let originalSet = KeywordSet.unreservedKeyword <> KeywordSet.colNameKeyword-      filteredSet = foldr HashSet.delete originalSet-   in \reservedKeywords -> label "identifier" $ ident <|> keywordNameFromSet (filteredSet reservedKeywords)---- |--- ==== References--- @--- ColLabel:---   |  IDENT---   |  unreserved_keyword---   |  col_name_keyword---   |  type_func_name_keyword---   |  reserved_keyword--- @-colLabel =-  label "column label"-    $ keywordNameFromSet KeywordSet.keyword-    <|> ident---- |--- >>> testParser qualifiedName "a.b"--- IndirectedQualifiedName (UnquotedIdent "a") (AttrNameIndirectionEl (UnquotedIdent "b") :| [])------ >>> testParser qualifiedName "a.-"--- ...--- expecting '*', column label, or white space------ ==== References--- @--- qualified_name:---   | ColId---   | ColId indirection--- @-qualifiedName =-  IndirectedQualifiedName <$> wrapToHead colId <*> (space *> indirection)-    <|> SimpleQualifiedName <$> colId--columnref = customizedColumnref colId--filteredColumnref keywords = customizedColumnref (filteredColId keywords)--customizedColumnref colId = do-  a <- wrapToHead colId-  endHead-  b <- optional (space *> indirection)-  return (Columnref a b)--anyName = customizedAnyName colId--filteredAnyName keywords = customizedAnyName (filteredColId keywords)--customizedAnyName colId = do-  a <- wrapToHead colId-  endHead-  b <- optional (space *> attrs)-  return (AnyName a b)--name = colId--nameList = sep1 commaSeparator name--cursorName = name---- |--- ==== References--- @--- func_name:---   | type_function_name---   | ColId indirection--- @-funcName =-  IndirectedFuncName <$> wrapToHead colId <*> (space *> indirection)-    <|> TypeFuncName <$> typeFunctionName---- |--- ==== References--- @--- type_function_name:---   | IDENT---   | unreserved_keyword---   | type_func_name_keyword--- @-typeFunctionName =-  keywordNameFromSet KeywordSet.typeFunctionName-    <|> ident---- |--- ==== References--- @--- indirection:---   | indirection_el---   | indirection indirection_el--- @-indirection = some indirectionEl---- |--- ==== References--- @--- indirection_el:---   | '.' attr_name---   | '.' '*'---   | '[' a_expr ']'---   | '[' opt_slice_bound ':' opt_slice_bound ']'--- opt_slice_bound:---   | a_expr---   | EMPTY--- @-indirectionEl =-  asum-    [ do-        char '.'-        endHead-        space-        AllIndirectionEl <$ char '*' <|> AttrNameIndirectionEl <$> attrName,-      do-        char '['-        endHead-        space-        a <--          asum-            [ do-                char ':'-                endHead-                space-                b <- optional aExpr-                return (SliceIndirectionEl Nothing b),-              do-                a <- aExpr-                asum-                  [ do-                      space-                      char ':'-                      space-                      b <- optional aExpr-                      return (SliceIndirectionEl (Just a) b),-                    return (ExprIndirectionEl a)-                  ]-            ]-        space-        char ']'-        return a-    ]---- |--- ==== References--- @--- attr_name:---   | ColLabel--- @-attrName = colLabel--keywordNameFromSet set = keywordNameByPredicate (Predicate.inSet set)--keywordNameByPredicate predicate =-  fmap UnquotedIdent-    $ filter-      (\a -> "Reserved keyword " <> show a <> " used as an identifier. If that's what you intend, you have to wrap it in double quotes.")-      predicate-      anyKeyword--anyKeyword = parse-  $ Megaparsec.label "keyword"-  $ do-    firstChar <- Megaparsec.satisfy Predicate.firstIdentifierChar-    remainder <- Megaparsec.takeWhileP Nothing Predicate.notFirstIdentifierChar-    return (Text.toLower (Text.cons firstChar remainder))---- | Expected keyword------ Wraps the head in 'Megaparsec.region' to pin the reported error offset to--- where this keyword check began. Without this, megaparsec >=9.8's stricter--- (and correct) '(<|>)' error-merging (fix for--- <https://github.com/mrkkrp/megaparsec/issues/412>) normalizes any error--- whose offset lands past the enclosing alternative's start back down to--- that start, discarding its \"expecting\" set unless the offset already--- matches exactly. Since every failed keyword branch consumes some--- identifier text before comparing, its offset always landed past the--- alternative's start, so wide 'asum'/'choice' chains of 'keyword' lost--- their combined expected-token sets under 9.8. Pinning the offset up front--- keeps every branch's offset aligned with the alternative's start, so--- their expected sets still union correctly.-keyword a = parse $ do-  off <- Megaparsec.getOffset-  Megaparsec.region (Megaparsec.setErrorOffset off) $ do-    firstChar <- Megaparsec.satisfy Predicate.firstIdentifierChar-    remainder <- Megaparsec.takeWhileP Nothing Predicate.notFirstIdentifierChar-    let parsedKeyword = Text.toLower (Text.cons firstChar remainder)-    if a == parsedKeyword then return parsedKeyword else empty---- |--- Consume a keyphrase, ignoring case and types of spaces between words.-keyphrase a =-  Text.words a-    & fmap (void . MegaparsecChar.string')-    & intersperse MegaparsecChar.space1-    & sequence_-    & (<* Megaparsec.notFollowedBy (Megaparsec.satisfy Predicate.notFirstIdentifierChar))-    & fmap (const (Text.toUpper a))-    & Megaparsec.label (show a)-    & parse-    & (<* endHead)---- * Typename--typeList = sep1 commaSeparator typename--typename =-  do-    a <- option False (keyword "setof" *> space1 $> True)-    b <- simpleTypename-    endHead-    c <- trueIfPresent (space *> char '?')-    asum-      [ do-          space1-          keyword "array"-          endHead-          d <- optional (space *> inBrackets iconst)-          e <- trueIfPresent (space *> char '?')-          return (Typename a b c (Just (ExplicitTypenameArrayDimensions d, e))),-        do-          space-          d <- arrayBounds-          endHead-          e <- trueIfPresent (space *> char '?')-          return (Typename a b c (Just (BoundsTypenameArrayDimensions d, e))),-        return (Typename a b c Nothing)-      ]--arrayBounds = sep1 space (inBrackets (optional iconst))--simpleTypename =-  asum-    $ [ do-          keyword "interval"-          endHead-          asum-            [ ConstIntervalSimpleTypename <$> Right <$> (space *> inParens iconst),-              ConstIntervalSimpleTypename <$> Left <$> optional (space *> interval)-            ],-        ConstDatetimeSimpleTypename <$> constDatetime,-        NumericSimpleTypename <$> numeric,-        BitSimpleTypename <$> bit,-        CharacterSimpleTypename <$> character,-        GenericTypeSimpleTypename <$> genericType-      ]--genericType = do-  a <- typeFunctionName-  endHead-  b <- optional (space *> attrs)-  c <- optional (space1 *> typeModifiers)-  return (GenericType a b c)--attrs = some (char '.' *> endHead *> space *> attrName)--typeModifiers = inParens exprList---- * Indexes--indexParams = sep1 commaSeparator indexElem--indexElem =-  IndexElem-    <$> (indexElemDef <* endHead)-    <*> optional (space1 *> collate)-    <*> optional (space1 *> class_)-    <*> optional (space1 *> ascDesc)-    <*> optional (space1 *> nullsOrder)--indexElemDef =-  ExprIndexElemDef <$> inParens aExpr-    <|> FuncIndexElemDef <$> funcExprWindowless-    <|> IdIndexElemDef <$> colId--collate = keyword "collate" *> space1 *> endHead *> anyName--class_ = filteredAnyName ["asc", "desc", "nulls"]--ascDesc = keyword "asc" $> AscAscDesc <|> keyword "desc" $> DescAscDesc--nullsOrder = keyword "nulls" *> space1 *> endHead *> (FirstNullsOrder <$ keyword "first" <|> LastNullsOrder <$ keyword "last")
− library/PostgresqlSyntax/Predicate.hs
@@ -1,71 +0,0 @@-{-# OPTIONS_GHC -Wno-redundant-constraints #-}--module PostgresqlSyntax.Predicate where--import qualified Data.HashSet as HashSet-import qualified PostgresqlSyntax.CharSet as CharSet-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import PostgresqlSyntax.Prelude---- * Generic---- |--- >>> test = oneOf [(==3), (==7), (==3), (==5)]--- >>> test 1--- False------ >>> test 3--- True------ >>> test 5--- True-oneOf :: [a -> Bool] -> a -> Bool-oneOf = foldr (\a b c -> a c || b c) (const False)--inSet :: (Eq a, Hashable a) => HashSet a -> a -> Bool-inSet = flip HashSet.member--hexDigit :: Char -> Bool-hexDigit = inSet CharSet.hexDigit--{--ident_start   [A-Za-z\200-\377_]--}-firstIdentifierChar :: Char -> Bool-firstIdentifierChar x = isAlpha x || x == '_' || x >= '\200' && x <= '\377'--{--ident_cont    [A-Za-z\200-\377_0-9\$]--}-notFirstIdentifierChar :: Char -> Bool-notFirstIdentifierChar x = isAlphaNum x || x == '_' || x == '$' || x >= '\200' && x <= '\377'--keyword :: Text -> Bool-keyword = inSet KeywordSet.keyword--unreservedKeyword :: Text -> Bool-unreservedKeyword = inSet KeywordSet.unreservedKeyword--colNameKeyword :: Text -> Bool-colNameKeyword = inSet KeywordSet.colNameKeyword--typeFuncNameKeyword :: Text -> Bool-typeFuncNameKeyword = inSet KeywordSet.typeFuncNameKeyword--reservedKeyword :: Text -> Bool-reservedKeyword = inSet KeywordSet.reservedKeyword--{-# NOINLINE symbolicBinOpChar #-}-symbolicBinOpChar :: Char -> Bool-symbolicBinOpChar = inSet CharSet.symbolicBinOp---- ** Op chars--opChar :: Char -> Bool-opChar = inSet CharSet.op--prohibitedOpChar :: Char -> Bool-prohibitedOpChar a = a == '+' || a == '-'--prohibitionLiftingOpChar :: Char -> Bool-prohibitionLiftingOpChar = inSet CharSet.prohibitionLiftingOp
− library/PostgresqlSyntax/Prelude.hs
@@ -1,96 +0,0 @@-module PostgresqlSyntax.Prelude-  ( module Exports,-    showAsText,-    suffixRec,-    extendMany,-  )-where--import Control.Applicative as Exports-import Control.Arrow as Exports hiding (first, second)-import Control.Category as Exports-import Control.Concurrent as Exports-import Control.Exception as Exports-import Control.Monad as Exports hiding (fail, forM, forM_, mapM, mapM_, msum, sequence, sequence_)-import Control.Monad.Fail as Exports-import Control.Monad.Fix as Exports hiding (fix)-import Control.Monad.IO.Class as Exports-import Control.Monad.ST as Exports-import Data.Bifunctor as Exports-import Data.Bits as Exports-import Data.Bool as Exports-import Data.ByteString as Exports (ByteString)-import Data.CaseInsensitive as Exports (CI, FoldCase)-import Data.Char as Exports-import Data.Coerce as Exports-import Data.Complex as Exports-import Data.Data as Exports-import Data.Dynamic as Exports-import Data.Either as Exports-import Data.Fixed as Exports-import Data.Foldable as Exports-import Data.Function as Exports hiding (id, (.))-import Data.Functor as Exports hiding (unzip)-import Data.Functor.Identity as Exports-import Data.HashMap.Strict as Exports (HashMap)-import Data.HashSet as Exports (HashSet)-import Data.Hashable as Exports (Hashable)-import Data.IORef as Exports-import Data.Int as Exports-import Data.Ix as Exports-import Data.List as Exports hiding (all, and, any, concat, concatMap, elem, find, foldl, foldl', foldl1, foldr, foldr1, isSubsequenceOf, mapAccumL, mapAccumR, maximum, maximumBy, minimum, minimumBy, notElem, or, product, sortOn, sum, uncons, unsnoc)-import Data.List.NonEmpty as Exports (NonEmpty (..))-import Data.Maybe as Exports-import Data.Monoid as Exports hiding (First (..), Last (..), (<>))-import Data.Ord as Exports-import Data.Proxy as Exports-import Data.Ratio as Exports-import Data.STRef as Exports-import Data.Semigroup as Exports-import Data.String as Exports-import Data.Text as Exports (Text)-import Data.Traversable as Exports-import Data.Tuple as Exports-import Data.Unique as Exports-import Data.Version as Exports-import Data.Void as Exports-import Data.Word as Exports-import Debug.Trace as Exports-import Foreign.ForeignPtr as Exports-import Foreign.Ptr as Exports-import Foreign.StablePtr as Exports-import Foreign.Storable as Exports hiding (alignment, sizeOf)-import GHC.Conc as Exports hiding (orElse, threadWaitRead, threadWaitReadSTM, threadWaitWrite, threadWaitWriteSTM, withMVar)-import GHC.Exts as Exports (IsList (Item, fromList), groupWith, inline, lazy, sortWith)-import GHC.Generics as Exports (Generic, Generic1)-import GHC.IO.Exception as Exports-import Numeric as Exports-import System.Environment as Exports-import System.Exit as Exports-import System.IO as Exports-import System.IO.Error as Exports-import System.IO.Unsafe as Exports-import System.Mem as Exports-import System.Mem.StableName as Exports-import System.Timeout as Exports-import Text.Printf as Exports (hPrintf, printf)-import Text.Read as Exports (Read (..), readEither, readMaybe)-import Unsafe.Coerce as Exports-import Prelude as Exports hiding (all, and, any, concat, concatMap, elem, fail, foldl, foldl1, foldr, foldr1, id, mapM, mapM_, maximum, minimum, notElem, or, product, sequence, sequence_, sum, (.))--showAsText :: (Show a) => a -> Text-showAsText = show >>> fromString---- |--- Compose a monad, which attempts to extend a value, based on the following input.--- It does so recursively until the suffix alternative fails.-suffixRec :: (MonadPlus m) => m a -> (a -> m a) -> m a-suffixRec base suffix = base >>= extendMany suffix--extendMany :: (MonadPlus m) => (a -> m a) -> a -> m a-extendMany attempt = loop-  where-    loop !state =-      optional (attempt state) >>= \case-        Nothing -> pure state-        Just newState -> loop newState
− library/PostgresqlSyntax/Rendering.hs
@@ -1,921 +0,0 @@-{-# OPTIONS_GHC -Wno-missing-signatures -Wno-dodgy-imports #-}--module PostgresqlSyntax.Rendering-  ( toText,-    module PostgresqlSyntax.Rendering,-  )-where--import qualified Data.Text as Text-import qualified Data.Text.Encoding as Text-import PostgresqlSyntax.Ast-import qualified PostgresqlSyntax.Extras.NonEmpty as NonEmpty-import PostgresqlSyntax.Extras.TextBuilder-import PostgresqlSyntax.Prelude hiding (aExpr, bit, fromList, many, option, sortBy, try)-import TextBuilder---- * Execution--toByteString :: TextBuilder -> ByteString-toByteString = Text.encodeUtf8 . toText---- * Helpers--commaNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder-commaNonEmpty = NonEmpty.intersperseFoldMap ", "--spaceNonEmpty :: (a -> TextBuilder) -> NonEmpty a -> TextBuilder-spaceNonEmpty = NonEmpty.intersperseFoldMap " "--lexemes :: [TextBuilder] -> TextBuilder-lexemes = mconcat . intersperse " "--optLexemes :: [Maybe TextBuilder] -> TextBuilder-optLexemes = lexemes . catMaybes--inParens :: TextBuilder -> TextBuilder-inParens a = "(" <> a <> ")"--inBrackets :: TextBuilder -> TextBuilder-inBrackets a = "[" <> a <> "]"--prefixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder-prefixMaybe a = foldMap (flip mappend " " . a)--suffixMaybe :: (a -> TextBuilder) -> Maybe a -> TextBuilder-suffixMaybe a = foldMap (mappend " " . a)---- * Statements--preparableStmt = \case-  SelectPreparableStmt a -> selectStmt a-  InsertPreparableStmt a -> insertStmt a-  UpdatePreparableStmt a -> updateStmt a-  DeletePreparableStmt a -> deleteStmt a-  CallPreparableStmt a -> callStmt a---- * Call--callStmt (CallStmt a) =-  "CALL " <> funcApplication a---- * Insert--insertStmt (InsertStmt a b c d e) =-  prefixMaybe withClause a-    <> "INSERT INTO "-    <> insertTarget b-    <> " "-    <> insertRest c-    <> suffixMaybe onConflict d-    <> suffixMaybe returningClause e--insertTarget (InsertTarget a b) =-  qualifiedName a <> foldMap (mappend " AS " . colId) b--insertRest = \case-  SelectInsertRest a b c ->-    optLexemes-      [ fmap (inParens . insertColumnList) a,-        fmap insertRestOverriding b,-        Just (selectStmt c)-      ]-  DefaultValuesInsertRest -> "DEFAULT VALUES"--insertRestOverriding a = "OVERRIDING " <> overrideKind a <> " VALUE"--overrideKind = \case-  UserOverrideKind -> "USER"-  SystemOverrideKind -> "SYSTEM"--insertColumnList = commaNonEmpty insertColumnItem--insertColumnItem (InsertColumnItem a b) = colId a <> suffixMaybe indirection b--onConflict (OnConflict a b) = "ON CONFLICT" <> suffixMaybe confExpr a <> " DO " <> onConflictDo b--onConflictDo = \case-  UpdateOnConflictDo a b -> "UPDATE SET " <> setClauseList a <> suffixMaybe whereClause b-  NothingOnConflictDo -> "NOTHING"--confExpr = \case-  WhereConfExpr a b -> inParens (indexParams a) <> suffixMaybe whereClause b-  ConstraintConfExpr a -> "ON CONSTRAINT " <> name a--returningClause = mappend "RETURNING " . targetList---- * Update--updateStmt (UpdateStmt a b c d e f) =-  prefixMaybe withClause a-    <> "UPDATE "-    <> relationExprOptAlias b-    <> " "-    <> "SET "-    <> setClauseList c-    <> suffixMaybe fromClause d-    <> suffixMaybe whereOrCurrentClause e-    <> suffixMaybe returningClause f--setClauseList = commaNonEmpty setClause--setClause = \case-  TargetSetClause a b -> setTarget a <> " = " <> aExpr b-  TargetListSetClause a b -> inParens (setTargetList a) <> " = " <> aExpr b--setTarget (SetTarget a b) = colId a <> suffixMaybe indirection b--setTargetList = commaNonEmpty setTarget---- * Delete--deleteStmt (DeleteStmt a b c d e) =-  prefixMaybe withClause a-    <> "DELETE FROM "-    <> relationExprOptAlias b-    <> suffixMaybe usingClause c-    <> suffixMaybe whereOrCurrentClause d-    <> suffixMaybe returningClause e--usingClause = mappend "USING " . fromList---- * Select--selectStmt = \case-  Left a -> selectNoParens a-  Right a -> selectWithParens a--selectNoParens (SelectNoParens a b c d e) =-  optLexemes-    [ fmap withClause a,-      Just (selectClause b),-      fmap sortClause c,-      fmap selectLimit d,-      fmap forLockingClause e-    ]--selectWithParens =-  inParens . \case-    NoParensSelectWithParens a -> selectNoParens a-    WithParensSelectWithParens a -> selectWithParens a--withClause (WithClause a b) =-  "WITH " <> bool "" "RECURSIVE " a <> commaNonEmpty commonTableExpr b--commonTableExpr (CommonTableExpr a b c d) =-  optLexemes-    [ Just (ident a),-      fmap (inParens . commaNonEmpty ident) b,-      Just "AS",-      fmap materialization c,-      Just (inParens (preparableStmt d))-    ]--materialization = bool "NOT MATERIALIZED" "MATERIALIZED"--selectLimit = \case-  LimitOffsetSelectLimit a b -> lexemes [limitClause a, offsetClause b]-  OffsetLimitSelectLimit a b -> lexemes [offsetClause a, limitClause b]-  LimitSelectLimit a -> limitClause a-  OffsetSelectLimit a -> offsetClause a--limitClause = \case-  LimitLimitClause a b -> "LIMIT " <> selectLimitValue a <> foldMap (mappend ", " . aExpr) b-  FetchOnlyLimitClause a b c ->-    optLexemes-      [ Just "FETCH",-        Just (firstOrNext a),-        fmap selectFetchFirstValue b,-        Just (rowOrRows c),-        Just "ONLY"-      ]--firstOrNext = bool "FIRST" "NEXT"--rowOrRows = bool "ROW" "ROWS"--selectFetchFirstValue = \case-  ExprSelectFetchFirstValue a -> cExpr a-  NumSelectFetchFirstValue a b -> bool "+" "-" a <> intOrFloat b--intOrFloat = either int64Dec doubleDec--selectLimitValue = \case-  ExprSelectLimitValue a -> aExpr a-  AllSelectLimitValue -> "ALL"--offsetClause = \case-  ExprOffsetClause a -> "OFFSET " <> aExpr a-  FetchFirstOffsetClause a b -> "OFFSET " <> selectFetchFirstValue a <> " " <> rowOrRows b--forLockingClause = \case-  ItemsForLockingClause a -> spaceNonEmpty forLockingItem a-  ReadOnlyForLockingClause -> "FOR READ ONLY"--forLockingItem (ForLockingItem a b c) =-  optLexemes-    [ Just (forLockingStrength a),-      fmap lockedRelsList b,-      fmap nowaitOrSkip c-    ]--forLockingStrength = \case-  UpdateForLockingStrength -> "FOR UPDATE"-  NoKeyUpdateForLockingStrength -> "FOR NO KEY UPDATE"-  ShareForLockingStrength -> "FOR SHARE"-  KeyForLockingStrength -> "FOR KEY SHARE"--lockedRelsList a = "OF " <> commaNonEmpty qualifiedName a--nowaitOrSkip = bool "NOWAIT" "SKIP LOCKED"--selectClause = either simpleSelect selectWithParens--simpleSelect = \case-  NormalSimpleSelect a b c d e f g ->-    optLexemes-      [ Just "SELECT",-        fmap targeting a,-        fmap intoClause b,-        fmap fromClause c,-        fmap whereClause d,-        fmap groupClause e,-        fmap havingClause f,-        fmap windowClause g-      ]-  ValuesSimpleSelect a -> valuesClause a-  TableSimpleSelect a -> "TABLE " <> relationExpr a-  BinSimpleSelect a b c d -> selectClause b <> " " <> selectBinOp a <> foldMap (mappend " " . allOrDistinct) c <> " " <> selectClause d--selectBinOp = \case-  UnionSelectBinOp -> "UNION"-  IntersectSelectBinOp -> "INTERSECT"-  ExceptSelectBinOp -> "EXCEPT"--targeting = \case-  NormalTargeting a -> targetList a-  AllTargeting a -> "ALL" <> suffixMaybe targetList a-  DistinctTargeting a b -> "DISTINCT" <> suffixMaybe onExpressionsClause a <> " " <> commaNonEmpty targetEl b--targetList = commaNonEmpty targetEl--onExpressionsClause a = "ON (" <> commaNonEmpty aExpr a <> ")"--targetEl = \case-  AliasedExprTargetEl a b -> aExpr a <> " AS " <> ident b-  ImplicitlyAliasedExprTargetEl a b -> aExpr a <> " " <> ident b-  ExprTargetEl a -> aExpr a-  AsteriskTargetEl -> "*"---- * Select Into--intoClause a = "INTO " <> optTempTableName a--optTempTableName = \case-  TemporaryOptTempTableName a b -> optLexemes [Just "TEMPORARY", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  TempOptTempTableName a b -> optLexemes [Just "TEMP", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  LocalTemporaryOptTempTableName a b -> optLexemes [Just "LOCAL TEMPORARY", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  LocalTempOptTempTableName a b -> optLexemes [Just "LOCAL TEMP", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  GlobalTemporaryOptTempTableName a b -> optLexemes [Just "GLOBAL TEMPORARY", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  GlobalTempOptTempTableName a b -> optLexemes [Just "GLOBAL TEMP", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  UnloggedOptTempTableName a b -> optLexemes [Just "UNLOGGED", bool Nothing (Just "TABLE") a, Just (qualifiedName b)]-  TableOptTempTableName a -> "TABLE " <> qualifiedName a-  QualifedOptTempTableName a -> qualifiedName a---- * From--fromClause a = "FROM " <> fromList a--fromList = commaNonEmpty tableRef--tableRef = \case-  RelationExprTableRef a b c ->-    optLexemes-      [ Just (relationExpr a),-        fmap aliasClause b,-        fmap tablesampleClause c-      ]-  FuncTableRef a b c ->-    optLexemes-      [ if a then Just "LATERAL" else Nothing,-        Just (funcTable b),-        fmap funcAliasClause c-      ]-  SelectTableRef a b c ->-    optLexemes-      [ if a then Just "LATERAL" else Nothing,-        Just (selectWithParens b),-        fmap aliasClause c-      ]-  JoinTableRef a b -> case b of-    Just c -> inParens (joinedTable a) <> " " <> aliasClause c-    Nothing -> joinedTable a--relationExpr = \case-  SimpleRelationExpr a b -> qualifiedName a <> bool "" " *" b-  OnlyRelationExpr a b -> "ONLY " <> bool qualifiedName (inParens . qualifiedName) b a--relationExprOptAlias (RelationExprOptAlias a b) = relationExpr a <> suffixMaybe optAlias b--optAlias (a, b) = bool "" "AS " a <> colId b--tablesampleClause (TablesampleClause a b c) =-  "TABLESAMPLE " <> funcName a <> " (" <> exprList b <> ")" <> suffixMaybe repeatableClause c--repeatableClause a = "REPEATABLE (" <> aExpr a <> ")"--funcTable = \case-  FuncExprFuncTable a b -> funcExprWindownless a <> bool "" " WITH ORDINALITY" b-  RowsFromFuncTable a b -> "ROWS FROM (" <> rowsfromList a <> ")" <> bool "" " WITH ORDINALITY" b--rowsfromItem (RowsfromItem a b) = funcExprWindownless a <> suffixMaybe colDefList b--rowsfromList = commaNonEmpty rowsfromItem--colDefList a = "AS (" <> tableFuncElementList a <> ")"--tableFuncElementList = commaNonEmpty tableFuncElement--tableFuncElement (TableFuncElement a b c) = colId a <> " " <> typename b <> suffixMaybe collateClause c--collateClause a = "COLLATE " <> anyName a--aliasClause (AliasClause a b c) =-  optLexemes-    [ if a then Just "AS" else Nothing,-      Just (ident b),-      fmap (inParens . commaNonEmpty ident) c-    ]--funcAliasClause = \case-  AliasFuncAliasClause a -> aliasClause a-  AsFuncAliasClause a -> "AS (" <> tableFuncElementList a <> ")"-  AsColIdFuncAliasClause a b -> "AS " <> colId a <> " (" <> tableFuncElementList b <> ")"-  ColIdFuncAliasClause a b -> colId a <> " (" <> tableFuncElementList b <> ")"--joinedTable = \case-  InParensJoinedTable a -> inParens (joinedTable a)-  MethJoinedTable a b c -> case a of-    CrossJoinMeth -> tableRef b <> " CROSS JOIN " <> tableRef c-    QualJoinMeth d e -> tableRef b <> suffixMaybe joinType d <> " JOIN " <> tableRef c <> " " <> joinQual e-    NaturalJoinMeth d -> tableRef b <> " NATURAL" <> suffixMaybe joinType d <> " JOIN " <> tableRef c--joinType = \case-  FullJoinType a -> "FULL" <> if a then " OUTER" else ""-  LeftJoinType a -> "LEFT" <> if a then " OUTER" else ""-  RightJoinType a -> "RIGHT" <> if a then " OUTER" else ""-  InnerJoinType -> "INNER"--joinQual = \case-  UsingJoinQual a -> "USING (" <> commaNonEmpty ident a <> ")"-  OnJoinQual a -> "ON " <> aExpr a---- * Where--whereClause a = "WHERE " <> aExpr a--whereOrCurrentClause = \case-  ExprWhereOrCurrentClause a -> "WHERE " <> aExpr a-  CursorWhereOrCurrentClause a -> "WHERE CURRENT OF " <> cursorName a---- * Group By--groupClause a = "GROUP BY " <> commaNonEmpty groupByItem a--groupByItem = \case-  ExprGroupByItem a -> aExpr a-  EmptyGroupingSetGroupByItem -> "()"-  RollupGroupByItem a -> "ROLLUP (" <> commaNonEmpty aExpr a <> ")"-  CubeGroupByItem a -> "CUBE (" <> commaNonEmpty aExpr a <> ")"-  GroupingSetsGroupByItem a -> "GROUPING SETS (" <> commaNonEmpty groupByItem a <> ")"---- * Having--havingClause a = "HAVING " <> aExpr a---- * Window--windowClause a = "WINDOW " <> commaNonEmpty windowDefinition a--windowDefinition (WindowDefinition a b) = ident a <> " AS " <> windowSpecification b--windowSpecification (WindowSpecification a b c d) =-  inParens-    $ optLexemes-      [ fmap ident a,-        fmap partitionClause b,-        fmap sortClause c,-        fmap frameClause d-      ]--partitionClause a = "PARTITION BY " <> commaNonEmpty aExpr a--frameClause (FrameClause a b c) =-  optLexemes-    [ Just (frameClauseMode a),-      Just (frameExtent b),-      fmap windowExclusionCause c-    ]--frameClauseMode = \case-  RangeFrameClauseMode -> "RANGE"-  RowsFrameClauseMode -> "ROWS"-  GroupsFrameClauseMode -> "GROUPS"--frameExtent = \case-  SingularFrameExtent a -> frameBound a-  BetweenFrameExtent a b -> "BETWEEN " <> frameBound a <> " AND " <> frameBound b--frameBound = \case-  UnboundedPrecedingFrameBound -> "UNBOUNDED PRECEDING"-  UnboundedFollowingFrameBound -> "UNBOUNDED FOLLOWING"-  CurrentRowFrameBound -> "CURRENT ROW"-  PrecedingFrameBound a -> aExpr a <> " PRECEDING"-  FollowingFrameBound a -> aExpr a <> " FOLLOWING"--windowExclusionCause = \case-  CurrentRowWindowExclusionClause -> "EXCLUDE CURRENT ROW"-  GroupWindowExclusionClause -> "EXCLUDE GROUP"-  TiesWindowExclusionClause -> "EXCLUDE TIES"-  NoOthersWindowExclusionClause -> "EXCLUDE NO OTHERS"---- * Order By--sortClause a = "ORDER BY " <> commaNonEmpty sortBy a--sortBy = \case-  UsingSortBy a b c -> aExpr a <> " USING " <> qualAllOp b <> suffixMaybe nullsOrder c-  AscDescSortBy a b c -> aExpr a <> suffixMaybe ascDesc b <> suffixMaybe nullsOrder c---- * Values--valuesClause a = "VALUES " <> commaNonEmpty (inParens . commaNonEmpty aExpr) a---- * Exprs--exprList = commaNonEmpty aExpr--aExpr = \case-  CExprAExpr a -> cExpr a-  TypecastAExpr a b -> aExpr a <> " :: " <> typename b-  CollateAExpr a b -> aExpr a <> " COLLATE " <> anyName b-  AtTimeZoneAExpr a b -> aExpr a <> " AT TIME ZONE " <> aExpr b-  PlusAExpr a -> "+ " <> aExpr a-  MinusAExpr a -> "- " <> aExpr a-  SymbolicBinOpAExpr a b c -> aExpr a <> " " <> symbolicExprBinOp b <> " " <> aExpr c-  PrefixQualOpAExpr a b -> qualOp a <> " " <> aExpr b-  SuffixQualOpAExpr a b -> aExpr a <> " " <> qualOp b-  AndAExpr a b -> aExpr a <> " AND " <> aExpr b-  OrAExpr a b -> aExpr a <> " OR " <> aExpr b-  NotAExpr a -> "NOT " <> aExpr a-  VerbalExprBinOpAExpr a b c d e -> aExpr a <> " " <> verbalExprBinOp b c <> " " <> aExpr d <> foldMap (mappend " ESCAPE " . aExpr) e-  ReversableOpAExpr a b c -> aExpr a <> " " <> aExprReversableOp b c-  IsnullAExpr a -> aExpr a <> " ISNULL"-  NotnullAExpr a -> aExpr a <> " NOTNULL"-  OverlapsAExpr a b -> row a <> " OVERLAPS " <> row b-  SubqueryAExpr a b c d -> aExpr a <> " " <> subqueryOp b <> " " <> subType c <> " " <> either selectWithParens (inParens . aExpr) d-  UniqueAExpr a -> "UNIQUE " <> selectWithParens a-  DefaultAExpr -> "DEFAULT"--bExpr = \case-  CExprBExpr a -> cExpr a-  TypecastBExpr a b -> bExpr a <> " :: " <> typename b-  PlusBExpr a -> "+ " <> bExpr a-  MinusBExpr a -> "- " <> bExpr a-  SymbolicBinOpBExpr a b c -> bExpr a <> " " <> symbolicExprBinOp b <> " " <> bExpr c-  QualOpBExpr a b -> qualOp a <> " " <> bExpr b-  IsOpBExpr a b c -> bExpr a <> " " <> bExprIsOp b c--cExpr = \case-  ColumnrefCExpr a -> columnref a-  AexprConstCExpr a -> aexprConst a-  ParamCExpr a b -> "$" <> intDec a <> foldMap indirection b-  InParensCExpr a b -> inParens (aExpr a) <> foldMap indirection b-  CaseCExpr a -> caseExpr a-  FuncCExpr a -> funcExpr a-  SelectWithParensCExpr a b -> selectWithParens a <> foldMap indirection b-  ExistsCExpr a -> "EXISTS " <> selectWithParens a-  ArrayCExpr a -> "ARRAY " <> either selectWithParens arrayExpr a-  ExplicitRowCExpr a -> explicitRow a-  ImplicitRowCExpr a -> implicitRow a-  GroupingCExpr a -> "GROUPING " <> inParens (exprList a)---- * Ops--aExprReversableOp a = \case-  NullAExprReversableOp -> bool "IS " "IS NOT " a <> "NULL"-  TrueAExprReversableOp -> bool "IS " "IS NOT " a <> "TRUE"-  FalseAExprReversableOp -> bool "IS " "IS NOT " a <> "FALSE"-  UnknownAExprReversableOp -> bool "IS " "IS NOT " a <> "UNKNOWN"-  DistinctFromAExprReversableOp b -> bool "IS " "IS NOT " a <> "DISTINCT FROM " <> aExpr b-  OfAExprReversableOp b -> bool "IS " "IS NOT " a <> "OF " <> inParens (typeList b)-  BetweenAExprReversableOp b c d -> bool "" "NOT " a <> bool "BETWEEN " "BETWEEN ASYMMETRIC " b <> bExpr c <> " AND " <> aExpr d-  BetweenSymmetricAExprReversableOp b c -> bool "" "NOT " a <> "BETWEEN SYMMETRIC " <> bExpr b <> " AND " <> aExpr c-  InAExprReversableOp b -> bool "" "NOT " a <> "IN " <> inExpr b-  DocumentAExprReversableOp -> bool "IS " "IS NOT " a <> "DOCUMENT"--verbalExprBinOp a =-  mappend (bool "" "NOT " a) . \case-    LikeVerbalExprBinOp -> "LIKE"-    IlikeVerbalExprBinOp -> "ILIKE"-    SimilarToVerbalExprBinOp -> "SIMILAR TO"--subqueryOp = \case-  AllSubqueryOp a -> allOp a-  AnySubqueryOp a -> "OPERATOR " <> inParens (anyOperator a)-  LikeSubqueryOp a -> bool "" "NOT " a <> "LIKE"-  IlikeSubqueryOp a -> bool "" "NOT " a <> "ILIKE"--bExprIsOp a =-  mappend (bool "IS " "IS NOT " a) . \case-    DistinctFromBExprIsOp b -> "DISTINCT FROM " <> bExpr b-    OfBExprIsOp a -> "OF " <> inParens (typeList a)-    DocumentBExprIsOp -> "DOCUMENT"--symbolicExprBinOp = \case-  MathSymbolicExprBinOp a -> mathOp a-  QualSymbolicExprBinOp a -> qualOp a--qualOp = \case-  OpQualOp a -> op a-  OperatorQualOp a -> "OPERATOR (" <> anyOperator a <> ")"--qualAllOp = \case-  AllQualAllOp a -> allOp a-  AnyQualAllOp a -> "OPERATOR (" <> anyOperator a <> ")"--op = text--anyOperator = \case-  AllOpAnyOperator a -> allOp a-  QualifiedAnyOperator a b -> colId a <> "." <> anyOperator b--allOp = \case-  OpAllOp a -> op a-  MathAllOp a -> mathOp a--mathOp = \case-  PlusMathOp -> char7 '+'-  MinusMathOp -> char7 '-'-  AsteriskMathOp -> char7 '*'-  SlashMathOp -> char7 '/'-  PercentMathOp -> char7 '%'-  ArrowUpMathOp -> char7 '^'-  ArrowLeftMathOp -> char7 '<'-  ArrowRightMathOp -> char7 '>'-  EqualsMathOp -> char7 '='-  LessEqualsMathOp -> "<="-  GreaterEqualsMathOp -> ">="-  ArrowLeftArrowRightMathOp -> "<>"-  ExclamationEqualsMathOp -> "!="--inExpr = \case-  SelectInExpr a -> selectWithParens a-  ExprListInExpr a -> inParens (exprList a)--caseExpr (CaseExpr a b c) =-  optLexemes-    [ Just "CASE",-      fmap aExpr a,-      Just (spaceNonEmpty whenClause b),-      fmap caseDefault c,-      Just "END"-    ]--whenClause (WhenClause a b) = "WHEN " <> aExpr a <> " THEN " <> aExpr b--caseDefault a = "ELSE " <> aExpr a--arrayExpr =-  inBrackets . \case-    ExprListArrayExpr a -> exprList a-    ArrayExprListArrayExpr a -> arrayExprList a-    EmptyArrayExpr -> mempty--arrayExprList = commaNonEmpty arrayExpr--row = \case-  ExplicitRowRow a -> explicitRow a-  ImplicitRowRow a -> implicitRow a--explicitRow a = "ROW " <> inParens (foldMap exprList a)--implicitRow (ImplicitRow a b) = inParens (exprList a <> ", " <> aExpr b)--funcApplication (FuncApplication a b) =-  funcName a <> "(" <> foldMap funcApplicationParams b <> ")"--funcApplicationParams = \case-  NormalFuncApplicationParams a b c ->-    optLexemes-      [ fmap allOrDistinct a,-        Just (commaNonEmpty funcArgExpr b),-        fmap sortClause c-      ]-  VariadicFuncApplicationParams a b c ->-    optLexemes-      [ fmap (flip mappend "," . commaNonEmpty funcArgExpr) a,-        Just "VARIADIC",-        Just (funcArgExpr b),-        fmap sortClause c-      ]-  StarFuncApplicationParams -> "*"--allOrDistinct = \case-  False -> "ALL"-  True -> "DISTINCT"--funcArgExpr = \case-  ExprFuncArgExpr a -> aExpr a-  ColonEqualsFuncArgExpr a b -> ident a <> " := " <> aExpr b-  EqualsGreaterFuncArgExpr a b -> ident a <> " => " <> aExpr b---- ** Func Expr--funcExpr = \case-  ApplicationFuncExpr a b c d ->-    optLexemes-      [ Just (funcApplication a),-        fmap withinGroupClause b,-        fmap filterClause c,-        fmap overClause d-      ]-  SubexprFuncExpr a -> funcExprCommonSubexpr a--funcExprWindownless = \case-  ApplicationFuncExprWindowless a -> funcApplication a-  CommonSubexprFuncExprWindowless a -> funcExprCommonSubexpr a--withinGroupClause a = "WITHIN GROUP (" <> sortClause a <> ")"--filterClause a = "FILTER (WHERE " <> aExpr a <> ")"--overClause = \case-  WindowOverClause a -> "OVER " <> windowSpecification a-  ColIdOverClause a -> "OVER " <> colId a--funcExprCommonSubexpr = \case-  CollationForFuncExprCommonSubexpr a -> "COLLATION FOR (" <> aExpr a <> ")"-  CurrentDateFuncExprCommonSubexpr -> "CURRENT_DATE"-  CurrentTimeFuncExprCommonSubexpr a -> "CURRENT_TIME" <> suffixMaybe (inParens . iconst) a-  CurrentTimestampFuncExprCommonSubexpr a -> "CURRENT_TIMESTAMP" <> suffixMaybe (inParens . iconst) a-  LocalTimeFuncExprCommonSubexpr a -> "LOCALTIME" <> suffixMaybe (inParens . iconst) a-  LocalTimestampFuncExprCommonSubexpr a -> "LOCALTIMESTAMP" <> suffixMaybe (inParens . iconst) a-  CurrentRoleFuncExprCommonSubexpr -> "CURRENT_ROLE"-  CurrentUserFuncExprCommonSubexpr -> "CURRENT_USER"-  SessionUserFuncExprCommonSubexpr -> "SESSION_USER"-  UserFuncExprCommonSubexpr -> "USER"-  CurrentCatalogFuncExprCommonSubexpr -> "CURRENT_CATALOG"-  CurrentSchemaFuncExprCommonSubexpr -> "CURRENT_SCHEMA"-  CastFuncExprCommonSubexpr a b -> "CAST (" <> aExpr a <> " AS " <> typename b <> ")"-  ExtractFuncExprCommonSubexpr a -> "EXTRACT (" <> foldMap extractList a <> ")"-  OverlayFuncExprCommonSubexpr a -> "OVERLAY (" <> overlayList a <> ")"-  PositionFuncExprCommonSubexpr a -> "POSITION (" <> foldMap positionList a <> ")"-  SubstringFuncExprCommonSubexpr a -> "SUBSTRING (" <> foldMap substrList a <> ")"-  TreatFuncExprCommonSubexpr a b -> "TREAT (" <> aExpr a <> " AS " <> typename b <> ")"-  TrimFuncExprCommonSubexpr a b -> "TRIM (" <> prefixMaybe trimModifier a <> trimList b <> ")"-  NullIfFuncExprCommonSubexpr a b -> "NULLIF (" <> aExpr a <> ", " <> aExpr b <> ")"-  CoalesceFuncExprCommonSubexpr a -> "COALESCE (" <> exprList a <> ")"-  GreatestFuncExprCommonSubexpr a -> "GREATEST (" <> exprList a <> ")"-  LeastFuncExprCommonSubexpr a -> "LEAST (" <> exprList a <> ")"--extractList (ExtractList a b) = extractArg a <> " FROM " <> aExpr b--extractArg = \case-  IdentExtractArg a -> ident a-  YearExtractArg -> "YEAR"-  MonthExtractArg -> "MONTH"-  DayExtractArg -> "DAY"-  HourExtractArg -> "HOUR"-  MinuteExtractArg -> "MINUTE"-  SecondExtractArg -> "SECOND"-  SconstExtractArg a -> sconst a--overlayList (OverlayList a b c d) = aExpr a <> " " <> overlayPlacing b <> " " <> substrFrom c <> suffixMaybe substrFor d--overlayPlacing a = "PLACING " <> aExpr a--positionList (PositionList a b) = bExpr a <> " IN " <> bExpr b--substrList = \case-  ExprSubstrList a b -> aExpr a <> " " <> substrListFromFor b-  ExprListSubstrList a -> exprList a--substrListFromFor = \case-  FromForSubstrListFromFor a b -> substrFrom a <> " " <> substrFor b-  ForFromSubstrListFromFor a b -> substrFor a <> " " <> substrFrom b-  FromSubstrListFromFor a -> substrFrom a-  ForSubstrListFromFor a -> substrFor a--substrFrom a = "FROM " <> aExpr a--substrFor a = "FOR " <> aExpr a--trimModifier = \case-  BothTrimModifier -> "BOTH"-  LeadingTrimModifier -> "LEADING"-  TrailingTrimModifier -> "TRAILING"--trimList = \case-  ExprFromExprListTrimList a b -> aExpr a <> " FROM " <> exprList b-  FromExprListTrimList a -> "FROM " <> exprList a-  ExprListTrimList a -> exprList a---- * AexprConsts--aexprConst = \case-  IAexprConst a -> iconst a-  FAexprConst a -> fconst a-  SAexprConst a -> sconst a-  BAexprConst a -> "B'" <> text a <> "'"-  XAexprConst a -> "X'" <> text a <> "'"-  FuncAexprConst a b c -> funcName a <> foldMap (inParens . funcAexprConstArgList) b <> " " <> sconst c-  ConstTypenameAexprConst a b -> constTypename a <> " " <> sconst b-  StringIntervalAexprConst a b -> "INTERVAL " <> sconst a <> suffixMaybe interval b-  IntIntervalAexprConst a b -> "INTERVAL " <> inParens (int64Dec a) <> " " <> sconst b-  BoolAexprConst a -> if a then "TRUE" else "FALSE"-  NullAexprConst -> "NULL"--iconst = int64Dec--fconst = doubleDec--sconst a = "'" <> text (Text.replace "'" "''" a) <> "'"--funcAexprConstArgList (FuncConstArgs a b) = commaNonEmpty funcArgExpr a <> suffixMaybe sortClause b--constTypename = \case-  NumericConstTypename a -> numeric a-  ConstBitConstTypename a -> constBit a-  ConstCharacterConstTypename a -> constCharacter a-  ConstDatetimeConstTypename a -> constDatetime a--numeric = \case-  IntNumeric -> "INT"-  IntegerNumeric -> "INTEGER"-  SmallintNumeric -> "SMALLINT"-  BigintNumeric -> "BIGINT"-  RealNumeric -> "REAL"-  FloatNumeric a -> "FLOAT" <> suffixMaybe (inParens . int64Dec) a-  DoublePrecisionNumeric -> "DOUBLE PRECISION"-  DecimalNumeric a -> "DECIMAL" <> suffixMaybe (inParens . commaNonEmpty aExpr) a-  DecNumeric a -> "DEC" <> suffixMaybe (inParens . commaNonEmpty aExpr) a-  NumericNumeric a -> "NUMERIC" <> suffixMaybe (inParens . commaNonEmpty aExpr) a-  BooleanNumeric -> "BOOLEAN"--bit (Bit a b) =-  optLexemes-    [ Just "BIT",-      bool Nothing (Just "VARYING") a,-      fmap (inParens . commaNonEmpty aExpr) b-    ]--constBit = bit--constCharacter (ConstCharacter a b) = character a <> suffixMaybe (inParens . int64Dec) b--character = \case-  CharacterCharacter a -> "CHARACTER" <> bool "" " VARYING" a-  CharCharacter a -> "CHAR" <> bool "" " VARYING" a-  VarcharCharacter -> "VARCHAR"-  NationalCharacterCharacter a -> "NATIONAL CHARACTER" <> bool "" " VARYING" a-  NationalCharCharacter a -> "NATIONAL CHAR" <> bool "" " VARYING" a-  NcharCharacter a -> "NCHAR" <> bool "" " VARYING" a--constDatetime = \case-  TimestampConstDatetime a b ->-    optLexemes-      [ Just "TIMESTAMP",-        fmap (inParens . int64Dec) a,-        fmap timezone b-      ]-  TimeConstDatetime a b ->-    optLexemes-      [ Just "TIME",-        fmap (inParens . int64Dec) a,-        fmap timezone b-      ]--timezone = \case-  False -> "WITH TIME ZONE"-  True -> "WITHOUT TIME ZONE"--interval = \case-  YearInterval -> "YEAR"-  MonthInterval -> "MONTH"-  DayInterval -> "DAY"-  HourInterval -> "HOUR"-  MinuteInterval -> "MINUTE"-  SecondInterval a -> intervalSecond a-  YearToMonthInterval -> "YEAR TO MONTH"-  DayToHourInterval -> "DAY TO HOUR"-  DayToMinuteInterval -> "DAY TO MINUTE"-  DayToSecondInterval a -> "DAY TO " <> intervalSecond a-  HourToMinuteInterval -> "HOUR TO MINUTE"-  HourToSecondInterval a -> "HOUR TO " <> intervalSecond a-  MinuteToSecondInterval a -> "MINUTE TO " <> intervalSecond a--intervalSecond = \case-  Nothing -> "SECOND"-  Just a -> "SECOND " <> inParens (int64Dec a)---- * Names and refs--columnref (Columnref a b) = colId a <> foldMap indirection b--ident = \case-  QuotedIdent a -> char7 '"' <> text (Text.replace "\"" "\"\"" a) <> char7 '"'-  UnquotedIdent a -> text a--qualifiedName = \case-  SimpleQualifiedName a -> ident a-  IndirectedQualifiedName a b -> ident a <> indirection b--indirection = foldMap indirectionEl--indirectionEl = \case-  AttrNameIndirectionEl a -> "." <> ident a-  AllIndirectionEl -> ".*"-  ExprIndirectionEl a -> "[" <> aExpr a <> "]"-  SliceIndirectionEl a b -> "[" <> foldMap aExpr a <> ":" <> foldMap aExpr b <> "]"--colId = ident--name = colId--cursorName = name--colLabel = ident--attrName = colLabel--typeFunctionName = ident--funcName = \case-  TypeFuncName a -> typeFunctionName a-  IndirectedFuncName a b -> colId a <> indirection b--anyName (AnyName a b) = colId a <> foldMap attrs b---- * Types--typename (Typename a b _ d) =-  bool "" "SETOF " a <> simpleTypename b <> foldMap typenameArrayDimensionsWithQuestionMark d--typenameArrayDimensionsWithQuestionMark (a, _) =-  typenameArrayDimensions a--typenameArrayDimensions = \case-  BoundsTypenameArrayDimensions a -> arrayBounds a-  ExplicitTypenameArrayDimensions a -> " ARRAY" <> foldMap (inBrackets . iconst) a--arrayBounds = spaceNonEmpty (inBrackets . foldMap iconst)--simpleTypename = \case-  GenericTypeSimpleTypename a -> genericType a-  NumericSimpleTypename a -> numeric a-  BitSimpleTypename a -> bit a-  CharacterSimpleTypename a -> character a-  ConstDatetimeSimpleTypename a -> constDatetime a-  ConstIntervalSimpleTypename a -> "INTERVAL" <> either (suffixMaybe interval) (mappend " " . inParens . iconst) a--genericType (GenericType a b c) = typeFunctionName a <> foldMap attrs b <> suffixMaybe typeModifiers c--attrs = foldMap (mappend "." . attrName)--typeModifiers = inParens . exprList--typeList = commaNonEmpty typename--subType = \case-  AnySubType -> "ANY"-  SomeSubType -> "SOME"-  AllSubType -> "ALL"---- * Indexes--indexParams = commaNonEmpty indexElem--indexElem (IndexElem a b c d e) =-  indexElemDef a-    <> suffixMaybe collate b-    <> suffixMaybe class_ c-    <> suffixMaybe ascDesc d-    <> suffixMaybe nullsOrder e--indexElemDef = \case-  IdIndexElemDef a -> colId a-  FuncIndexElemDef a -> funcExprWindownless a-  ExprIndexElemDef a -> inParens (aExpr a)--collate = mappend "COLLATE " . anyName--class_ = anyName--ascDesc = \case-  AscAscDesc -> "ASC"-  DescAscDesc -> "DESC"--nullsOrder = \case-  FirstNullsOrder -> "NULLS FIRST"-  LastNullsOrder -> "NULLS LAST"
− library/PostgresqlSyntax/Validation.hs
@@ -1,51 +0,0 @@-module PostgresqlSyntax.Validation where--import qualified Data.Text as Text-import qualified PostgresqlSyntax.KeywordSet as KeywordSet-import qualified PostgresqlSyntax.Predicate as Predicate-import PostgresqlSyntax.Prelude--{--The operator name is a sequence of up to NAMEDATALEN-1 (63 by default)-characters from the following list:--+ - * / < > = ~ ! @ # % ^ & | ` ?--There are a few restrictions on your choice of name:--- and /* cannot appear anywhere in an operator name,-since they will be taken as the start of a comment.--A multicharacter operator name cannot end in + or -,-unless the name also contains at least one of these characters:--~ ! @ # % ^ & | ` ?--For example, @- is an allowed operator name, but *- is not.-This restriction allows PostgreSQL to parse SQL-compliant-commands without requiring spaces between tokens.-The use of => as an operator name is deprecated.-It may be disallowed altogether in a future release.--The operator != is mapped to <> on input,-so these two names are always equivalent.--}-op :: Text -> Maybe Text-op a =-  if Text.null a-    then Just ("Operator is empty")-    else-      if Text.isInfixOf "--" a-        then Just ("Operator contains a prohibited \"--\" sequence: " <> a)-        else-          if Text.isInfixOf "/*" a-            then Just ("Operator contains a prohibited \"/*\" sequence: " <> a)-            else-              if Predicate.inSet KeywordSet.nonOp a-                then Just ("Operator is not generic: " <> a)-                else-                  if Text.find Predicate.prohibitionLiftingOpChar a & isJust-                    then Nothing-                    else-                      if Predicate.prohibitedOpChar (Text.last a)-                        then Just ("Operator ends with a prohibited char: " <> a)-                        else Nothing
nesting-bench/Main.hs view
@@ -11,13 +11,9 @@ -- as a timeout instead of hanging the run. module Main where -import Control.Concurrent (forkIO, threadDelay) import Control.Concurrent.MVar-import Control.DeepSeq (force)-import Control.Exception (evaluate)-import Data.Text (Text) import qualified Data.Text as Text-import qualified PostgresqlSyntax.Parsing as Parsing+import PostgresqlSyntax (AExpr, parse) import System.Clock import Prelude @@ -58,7 +54,7 @@ time :: Text -> IO Double time input = do   start <- getTime Monotonic-  _ <- evaluate (force (either (const "err") (const "ok") (Parsing.run Parsing.aExpr input) :: String))+  _ <- evaluate (force (either (const "err") (const "ok") (parse @AExpr mempty input) :: String))   end <- getTime Monotonic   pure (fromIntegral (toNanoSecs (diffTimeSpec end start)) / 1e9) 
postgresql-syntax.cabal view
@@ -1,12 +1,10 @@ cabal-version: 3.0 name: postgresql-syntax-version: 0.4.5.0+version: 0.5.0.0 category: Database, PostgreSQL, Parsing synopsis: PostgreSQL AST parsing and rendering description:   Postgres syntax tree and related utils extracted from the \"hasql-th\" package.-  The API is in a rather raw \"guts out\" state with most documentation lacking,-  but the codebase is well tested.  homepage: https://github.com/nikita-volkov/postgresql-syntax bug-reports: https://github.com/nikita-volkov/postgresql-syntax/issues@@ -24,7 +22,6 @@   default-language: Haskell2010   default-extensions:     ApplicativeDo-    Arrows     BangPatterns     ConstraintKinds     DataKinds@@ -51,35 +48,187 @@     OverloadedStrings     ParallelListComp     PatternGuards-    QuasiQuotes     RankNTypes     RecordWildCards     ScopedTypeVariables     StandaloneDeriving-    TemplateHaskell     TupleSections     TypeApplications     TypeFamilies     TypeOperators     UnboxedTuples -library+library internal   import: base-settings-  hs-source-dirs: library+  hs-source-dirs: library-internal   exposed-modules:     PostgresqlSyntax.Ast-    PostgresqlSyntax.KeywordSet-    PostgresqlSyntax.Parsing-    PostgresqlSyntax.Rendering-    PostgresqlSyntax.Validation--  other-modules:+    PostgresqlSyntax.Ast.AExpr+    PostgresqlSyntax.Ast.AexprConst+    PostgresqlSyntax.Ast.AExprReversableOp+    PostgresqlSyntax.Ast.AliasClause+    PostgresqlSyntax.Ast.AllOp+    PostgresqlSyntax.Ast.AnyName+    PostgresqlSyntax.Ast.AnyOperator+    PostgresqlSyntax.Ast.ArrayBounds+    PostgresqlSyntax.Ast.ArrayExpr+    PostgresqlSyntax.Ast.ArrayExprList+    PostgresqlSyntax.Ast.AscDesc+    PostgresqlSyntax.Ast.Attrs+    PostgresqlSyntax.Ast.Bconst+    PostgresqlSyntax.Ast.BExpr+    PostgresqlSyntax.Ast.BExprIsOp+    PostgresqlSyntax.Ast.Bit+    PostgresqlSyntax.Ast.CallStmt+    PostgresqlSyntax.Ast.CaseExpr+    PostgresqlSyntax.Ast.CExpr+    PostgresqlSyntax.Ast.Character+    PostgresqlSyntax.Ast.Columnref+    PostgresqlSyntax.Ast.CommonTableExpr+    PostgresqlSyntax.Ast.ConfExpr+    PostgresqlSyntax.Ast.ConstCharacter+    PostgresqlSyntax.Ast.ConstDatetime+    PostgresqlSyntax.Ast.ConstTypename+    PostgresqlSyntax.Ast.DeleteStmt+    PostgresqlSyntax.Ast.ExplicitRow+    PostgresqlSyntax.Ast.ExprList+    PostgresqlSyntax.Ast.ExtractArg+    PostgresqlSyntax.Ast.ExtractList+    PostgresqlSyntax.Ast.Fconst+    PostgresqlSyntax.Ast.ForLockingClause+    PostgresqlSyntax.Ast.ForLockingItem+    PostgresqlSyntax.Ast.ForLockingStrength+    PostgresqlSyntax.Ast.FrameBound+    PostgresqlSyntax.Ast.FrameClause+    PostgresqlSyntax.Ast.FrameClauseMode+    PostgresqlSyntax.Ast.FrameExtent+    PostgresqlSyntax.Ast.FromClause+    PostgresqlSyntax.Ast.FromList+    PostgresqlSyntax.Ast.FuncAliasClause+    PostgresqlSyntax.Ast.FuncApplication+    PostgresqlSyntax.Ast.FuncApplicationParams+    PostgresqlSyntax.Ast.FuncArgExpr+    PostgresqlSyntax.Ast.FuncConstArgs+    PostgresqlSyntax.Ast.FuncExpr+    PostgresqlSyntax.Ast.FuncExprCommonSubexpr+    PostgresqlSyntax.Ast.FuncExprWindowless+    PostgresqlSyntax.Ast.FuncName+    PostgresqlSyntax.Ast.FuncTable+    PostgresqlSyntax.Ast.GenericType+    PostgresqlSyntax.Ast.GroupByItem+    PostgresqlSyntax.Ast.GroupClause+    PostgresqlSyntax.Ast.HavingClause+    PostgresqlSyntax.Ast.Iconst+    PostgresqlSyntax.Ast.Ident+    PostgresqlSyntax.Ast.ImplicitRow+    PostgresqlSyntax.Ast.IndexElem+    PostgresqlSyntax.Ast.IndexElemDef+    PostgresqlSyntax.Ast.IndexParams+    PostgresqlSyntax.Ast.Indirection+    PostgresqlSyntax.Ast.IndirectionEl+    PostgresqlSyntax.Ast.InExpr+    PostgresqlSyntax.Ast.InsertColumnItem+    PostgresqlSyntax.Ast.InsertColumnList+    PostgresqlSyntax.Ast.InsertRest+    PostgresqlSyntax.Ast.InsertStmt+    PostgresqlSyntax.Ast.InsertTarget+    PostgresqlSyntax.Ast.Interval+    PostgresqlSyntax.Ast.IntervalSecond+    PostgresqlSyntax.Ast.IntoClause+    PostgresqlSyntax.Ast.JoinedTable+    PostgresqlSyntax.Ast.JoinMeth+    PostgresqlSyntax.Ast.JoinQual+    PostgresqlSyntax.Ast.JoinType+    PostgresqlSyntax.Ast.LimitClause+    PostgresqlSyntax.Ast.MathOp+    PostgresqlSyntax.Ast.NameList+    PostgresqlSyntax.Ast.NullsOrder+    PostgresqlSyntax.Ast.Numeric+    PostgresqlSyntax.Ast.OffsetClause+    PostgresqlSyntax.Ast.OnConflict+    PostgresqlSyntax.Ast.OnConflictDo+    PostgresqlSyntax.Ast.Op+    PostgresqlSyntax.Ast.OptOrdinality+    PostgresqlSyntax.Ast.OptTempTableName+    PostgresqlSyntax.Ast.OptVarying+    PostgresqlSyntax.Ast.OverClause+    PostgresqlSyntax.Ast.OverlayList+    PostgresqlSyntax.Ast.OverrideKind+    PostgresqlSyntax.Ast.PositionList+    PostgresqlSyntax.Ast.PreparableStmt+    PostgresqlSyntax.Ast.QualAllOp+    PostgresqlSyntax.Ast.QualifiedName+    PostgresqlSyntax.Ast.QualOp+    PostgresqlSyntax.Ast.RelationExpr+    PostgresqlSyntax.Ast.RelationExprOptAlias+    PostgresqlSyntax.Ast.ReturningClause+    PostgresqlSyntax.Ast.Row+    PostgresqlSyntax.Ast.RowsfromItem+    PostgresqlSyntax.Ast.RowsfromList+    PostgresqlSyntax.Ast.Sconst+    PostgresqlSyntax.Ast.SelectBinOp+    PostgresqlSyntax.Ast.SelectClause+    PostgresqlSyntax.Ast.SelectFetchFirstValue+    PostgresqlSyntax.Ast.SelectLimit+    PostgresqlSyntax.Ast.SelectLimitValue+    PostgresqlSyntax.Ast.SelectNoParens+    PostgresqlSyntax.Ast.SelectStmt+    PostgresqlSyntax.Ast.SelectWithParens+    PostgresqlSyntax.Ast.SetClause+    PostgresqlSyntax.Ast.SetClauseList+    PostgresqlSyntax.Ast.SetTarget+    PostgresqlSyntax.Ast.SetTargetList+    PostgresqlSyntax.Ast.SimpleSelect+    PostgresqlSyntax.Ast.SimpleTypename+    PostgresqlSyntax.Ast.SortBy+    PostgresqlSyntax.Ast.SortClause+    PostgresqlSyntax.Ast.SubqueryOp+    PostgresqlSyntax.Ast.SubstrList+    PostgresqlSyntax.Ast.SubstrListFromFor+    PostgresqlSyntax.Ast.SubType+    PostgresqlSyntax.Ast.SymbolicExprBinOp+    PostgresqlSyntax.Ast.TableFuncElement+    PostgresqlSyntax.Ast.TableFuncElementList+    PostgresqlSyntax.Ast.TableRef+    PostgresqlSyntax.Ast.TablesampleClause+    PostgresqlSyntax.Ast.TargetEl+    PostgresqlSyntax.Ast.Targeting+    PostgresqlSyntax.Ast.TargetList+    PostgresqlSyntax.Ast.Timezone+    PostgresqlSyntax.Ast.TrimList+    PostgresqlSyntax.Ast.TrimModifier+    PostgresqlSyntax.Ast.TypeList+    PostgresqlSyntax.Ast.Typename+    PostgresqlSyntax.Ast.TypenameArrayDimensions+    PostgresqlSyntax.Ast.UpdateStmt+    PostgresqlSyntax.Ast.UsingClause+    PostgresqlSyntax.Ast.ValuesClause+    PostgresqlSyntax.Ast.VerbalExprBinOp+    PostgresqlSyntax.Ast.WhenClause+    PostgresqlSyntax.Ast.WhenClauseList+    PostgresqlSyntax.Ast.WhereClause+    PostgresqlSyntax.Ast.WhereOrCurrentClause+    PostgresqlSyntax.Ast.WindowClause+    PostgresqlSyntax.Ast.WindowDefinition+    PostgresqlSyntax.Ast.WindowExclusionClause+    PostgresqlSyntax.Ast.WindowSpecification+    PostgresqlSyntax.Ast.WithClause+    PostgresqlSyntax.Ast.Xconst     PostgresqlSyntax.CharSet+    PostgresqlSyntax.Extras.Error     PostgresqlSyntax.Extras.HeadedMegaparsec     PostgresqlSyntax.Extras.NonEmpty     PostgresqlSyntax.Extras.TextBuilder+    PostgresqlSyntax.Helpers.Gens+    PostgresqlSyntax.Helpers.Parsers+    PostgresqlSyntax.Helpers.Shrinks+    PostgresqlSyntax.Helpers.TextBuilders+    PostgresqlSyntax.IsAst+    PostgresqlSyntax.KeywordSet     PostgresqlSyntax.Predicate     PostgresqlSyntax.Prelude+    PostgresqlSyntax.Settings+    PostgresqlSyntax.Validation    build-depends:     base >=4.12 && <5,@@ -89,32 +238,194 @@     headed-megaparsec >=0.2.0.1 && <0.3,     megaparsec >=9.2 && <10,     parser-combinators >=1.3 && <1.4,+    QuickCheck >=2.17 && <3,     text >=1 && <3,     text-builder >=1 && <1.1,     unordered-containers >=0.2.16 && <0.3, -test-suite tasty-test+library   import: base-settings-  type: exitcode-stdio-1.0-  hs-source-dirs: tasty-test-  main-is: Main.hs-  ghc-options: -threaded+  hs-source-dirs: library+  exposed-modules:+    PostgresqlSyntax+   build-depends:-    postgresql-syntax,-    rerebase <2,-    tasty >=1.2.3 && <2,-    tasty-hunit >=0.10 && <0.11,+    postgresql-syntax:internal -test-suite hedgehog-test+test-suite hspec-test   import: base-settings   type: exitcode-stdio-1.0-  hs-source-dirs: hedgehog-test+  hs-source-dirs: hspec-test   main-is: Main.hs-  ghc-options: -threaded-  other-modules: Main.Gen+  other-modules:+    Ast.AexprConstSpec+    Ast.AExprReversableOpSpec+    Ast.AExprSpec+    Ast.AliasClauseSpec+    Ast.AllOpSpec+    Ast.AnyNameSpec+    Ast.AnyOperatorSpec+    Ast.ArrayBoundsSpec+    Ast.ArrayExprListSpec+    Ast.ArrayExprSpec+    Ast.AscDescSpec+    Ast.AttrsSpec+    Ast.BconstSpec+    Ast.BExprIsOpSpec+    Ast.BExprSpec+    Ast.BitSpec+    Ast.CallStmtSpec+    Ast.CaseExprSpec+    Ast.CExprSpec+    Ast.CharacterSpec+    Ast.ColumnrefSpec+    Ast.CommonTableExprSpec+    Ast.ConfExprSpec+    Ast.ConstCharacterSpec+    Ast.ConstDatetimeSpec+    Ast.ConstTypenameSpec+    Ast.DeleteStmtSpec+    Ast.ExplicitRowSpec+    Ast.ExprListSpec+    Ast.ExtractArgSpec+    Ast.ExtractListSpec+    Ast.FconstSpec+    Ast.ForLockingClauseSpec+    Ast.ForLockingItemSpec+    Ast.ForLockingStrengthSpec+    Ast.FrameBoundSpec+    Ast.FrameClauseModeSpec+    Ast.FrameClauseSpec+    Ast.FrameExtentSpec+    Ast.FromClauseSpec+    Ast.FromListSpec+    Ast.FuncAliasClauseSpec+    Ast.FuncApplicationParamsSpec+    Ast.FuncApplicationSpec+    Ast.FuncArgExprSpec+    Ast.FuncConstArgsSpec+    Ast.FuncExprCommonSubexprSpec+    Ast.FuncExprSpec+    Ast.FuncExprWindowlessSpec+    Ast.FuncNameSpec+    Ast.FuncTableSpec+    Ast.GenericTypeSpec+    Ast.GroupByItemSpec+    Ast.GroupClauseSpec+    Ast.HavingClauseSpec+    Ast.IconstSpec+    Ast.IdentSpec+    Ast.ImplicitRowSpec+    Ast.IndexElemDefSpec+    Ast.IndexElemSpec+    Ast.IndexParamsSpec+    Ast.IndirectionElSpec+    Ast.IndirectionSpec+    Ast.InExprSpec+    Ast.InsertColumnItemSpec+    Ast.InsertColumnListSpec+    Ast.InsertRestSpec+    Ast.InsertStmtSpec+    Ast.InsertTargetSpec+    Ast.IntervalSecondSpec+    Ast.IntervalSpec+    Ast.IntoClauseSpec+    Ast.JoinedTableSpec+    Ast.JoinMethSpec+    Ast.JoinQualSpec+    Ast.JoinTypeSpec+    Ast.LimitClauseSpec+    Ast.MathOpSpec+    Ast.NameListSpec+    Ast.NullsOrderSpec+    Ast.NumericSpec+    Ast.OffsetClauseSpec+    Ast.OnConflictDoSpec+    Ast.OnConflictSpec+    Ast.OpSpec+    Ast.OptOrdinalitySpec+    Ast.OptTempTableNameSpec+    Ast.OptVaryingSpec+    Ast.OverClauseSpec+    Ast.OverlayListSpec+    Ast.OverrideKindSpec+    Ast.PositionListSpec+    Ast.PreparableStmtSpec+    Ast.QualAllOpSpec+    Ast.QualifiedNameSpec+    Ast.QualOpSpec+    Ast.RelationExprOptAliasSpec+    Ast.RelationExprSpec+    Ast.ReturningClauseSpec+    Ast.RowsfromItemSpec+    Ast.RowsfromListSpec+    Ast.RowSpec+    Ast.SconstSpec+    Ast.SelectBinOpSpec+    Ast.SelectClauseSpec+    Ast.SelectFetchFirstValueSpec+    Ast.SelectLimitSpec+    Ast.SelectLimitValueSpec+    Ast.SelectNoParensSpec+    Ast.SelectStmtSpec+    Ast.SelectWithParensSpec+    Ast.SetClauseListSpec+    Ast.SetClauseSpec+    Ast.SetTargetListSpec+    Ast.SetTargetSpec+    Ast.SimpleSelectSpec+    Ast.SimpleTypenameSpec+    Ast.SortBySpec+    Ast.SortClauseSpec+    Ast.SubqueryOpSpec+    Ast.SubstrListFromForSpec+    Ast.SubstrListSpec+    Ast.SubTypeSpec+    Ast.SymbolicExprBinOpSpec+    Ast.TableFuncElementListSpec+    Ast.TableFuncElementSpec+    Ast.TableRefSpec+    Ast.TablesampleClauseSpec+    Ast.TargetElSpec+    Ast.TargetingSpec+    Ast.TargetListSpec+    Ast.TimezoneSpec+    Ast.TrimListSpec+    Ast.TrimModifierSpec+    Ast.TypeListSpec+    Ast.TypenameArrayDimensionsSpec+    Ast.TypenameSpec+    Ast.UpdateStmtSpec+    Ast.UsingClauseSpec+    Ast.ValuesClauseSpec+    Ast.VerbalExprBinOpSpec+    Ast.WhenClauseListSpec+    Ast.WhenClauseSpec+    Ast.WhereClauseSpec+    Ast.WhereOrCurrentClauseSpec+    Ast.WindowClauseSpec+    Ast.WindowDefinitionSpec+    Ast.WindowExclusionClauseSpec+    Ast.WindowSpecificationSpec+    Ast.WithClauseSpec+    Ast.XconstSpec+    Helpers.Expectations+    Helpers.Specs+    Spec++  ghc-options:+    -threaded+    -rtsopts+    -with-rtsopts=-N++  build-tool-depends:+    hspec-discover:hspec-discover >=2.10 && <3+   build-depends:-    hedgehog >=1.0.1 && <2,-    postgresql-syntax,+    hspec >=2.10 && <3,+    megaparsec >=9.2 && <10,+    postgresql-syntax:internal,+    QuickCheck >=2.17 && <3,     rerebase >=1.6.1 && <2,  benchmark keyword-bench@@ -122,18 +433,16 @@   type: exitcode-stdio-1.0   hs-source-dirs:     bench-    hedgehog-test    main-is: Main.hs   ghc-options: -O2-  other-modules: Main.Gen   build-depends:     containers >=0.4 && <1,     criterion >=1.6 && <1.7,     headed-megaparsec >=0.2.0.1 && <0.3,-    hedgehog >=1.0.1 && <2,     megaparsec >=9.2 && <10,     postgresql-syntax,+    QuickCheck >=2.17 && <3,     rerebase >=1.6.1 && <2,  benchmark nesting-bench@@ -147,6 +456,5 @@    build-depends:     clock >=0.8 && <1,-    deepseq >=1.4 && <2,     postgresql-syntax,     rerebase >=1.6.1 && <2,
− tasty-test/Main.hs
@@ -1,157 +0,0 @@-module Main where--import qualified Data.List.NonEmpty as NonEmpty-import qualified Data.Text as Text-import PostgresqlSyntax.Ast-import qualified PostgresqlSyntax.Parsing as Parsing-import qualified PostgresqlSyntax.Rendering as Rendering-import Test.Tasty-import Test.Tasty.HUnit-import Prelude hiding (assert)--main :: IO ()-main =-  defaultMain-    $ testGroup-      ""-      [ testGroup "Parsers"-          $ let testParserOnAllInputs parserName parser inputs =-                  testCase parserName-                    $ forM_ inputs-                    $ \input -> case Parsing.run parser input of-                      Left err -> assertFailure (err <> "\ninput: " <> Text.unpack input)-                      Right _ -> return ()-             in [ testParserOnAllInputs-                    "preparableStmt"-                    Parsing.preparableStmt-                    [ "select i :: int8 from 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",-                      -- FOR locking clause before LIMIT (PostgreSQL accepts both orderings)-                      "select * from items for update limit 1",-                      "select * from items limit 1 for update",-                      "select * from items for share limit 10",-                      "select * from items for no key update limit 1",-                      "select * from items for key share limit 1",-                      "select * from items for update of items nowait limit 1",-                      "select * from items for update skip locked limit 1",-                      "select * from items order by id for update limit 1",-                      "select * from items for update offset 5 limit 10"-                    ],-                  testParserOnAllInputs-                    "typename"-                    Parsing.typename-                    [ "int4[]",-                      "int4[][]",-                      "int4?[]",-                      "int4?[]?",-                      "aa array",-                      "DOUBLE PRECISION",-                      "bool",-                      "int2",-                      "int4",-                      "int8",-                      "float4",-                      "float8",-                      "numeric",-                      "char",-                      "text",-                      "bytea",-                      "date",-                      "timestamp",-                      "timestamptz",-                      "time",-                      "timetz",-                      "interval",-                      "uuid",-                      "inet",-                      "json",-                      "jsonb"-                    ],-                  testParserOnAllInputs-                    "sconst"-                    Parsing.sconst-                    [ "'it''s good'",-                      "$$it's good$$",-                      "$x$it's good$x$"-                    ]-                ],-        testGroup "Nesting depth" nestingTests,-        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"-                    ]-                    "(51,\"offset=51:\\nexpecting white space\\n\")"-                ]-      ]---- |--- Regression tests for the parser's behaviour on deeply nested parentheses.------ The parser used to take time exponential in the nesting depth, because--- several grammar alternatives each parsed the content of a parenthesised--- group before discovering they did not apply. Every input here is trivial in--- size; before the fix, all of them ran for longer than a person will wait.------ Each case is given a generous wall-clock budget. The point is not to measure--- performance — 'nesting-bench' does that — but to fail loudly if the--- exponential behaviour ever comes back.-nestingTests :: [TestTree]-nestingTests =-  [ parsesWithin "redundant parens, depth 50" 5 Parsing.aExpr-      $ Text.replicate 50 "("-      <> "a + b"-      <> Text.replicate 50 ")",-    parsesWithin "redundant parens around a select, depth 50" 5 Parsing.preparableStmt-      $ "select "-      <> Text.replicate 50 "("-      <> "a + b"-      <> Text.replicate 50 ")",-    parsesWithin "sum of COALESCE terms in two wrapped groups" 5 Parsing.aExpr-      $ let terms off = Text.intercalate " + " ["coalesce(c" <> Text.pack (show (off + i)) <> ", 0)" | i <- [1 .. 24 :: Int]]-         in Text.replicate 6 "(" <> "(" <> terms 0 <> ") - (" <> terms 24 <> ")" <> Text.replicate 6 ")",-    -- The parenthesised sub-select has two possible representations; see the-    -- "Canonical shape" note on 'PostgresqlSyntax.Parsing.selectWithParensBody'.-    testCase "redundant parens around a sub-select are canonicalised" $ do-      let expected =-            WithParensSelectWithParens-              . NoParensSelectWithParens-              <$> Parsing.run Parsing.selectNoParens "select 1"-      Parsing.run Parsing.selectWithParens "((select 1))" @?= expected,-    testCase "OVERLAPS still parses" $ do-      let render = Rendering.toText . Rendering.aExpr-      fmap render (Parsing.run Parsing.aExpr "(1, 2) overlaps (3, 4)")-        @?= Right "(1, 2) OVERLAPS (3, 4)"-      fmap render (Parsing.run Parsing.aExpr "row(1, 2) overlaps row(3, 4)")-        @?= Right "ROW (1, 2) OVERLAPS ROW (3, 4)"-  ]-  where-    parsesWithin name seconds parser input =-      testCase name $ do-        result <- timeout (seconds * 1000000) $ case Parsing.run parser input of-          Left err -> assertFailure (err <> "\ninput: " <> Text.unpack input)-          Right _ -> return ()-        case result of-          Nothing -> assertFailure ("Did not finish parsing within " <> show seconds <> "s")-          Just () -> return ()