{-| Module: IHP.IDE.SchemaDesigner.Types Description: Types for representing an AST of SQL DDL Copyright: (c) digitally induced GmbH, 2020 -} module IHP.IDE.SchemaDesigner.Types where import IHP.Prelude data Statement = -- | CREATE TABLE name ( columns ); StatementCreateTable { unsafeGetCreateTable :: CreateTable } -- | CREATE TYPE name AS ENUM ( values ); | CreateEnumType { name :: Text, values :: [Text] } -- | DROP TYPE name; | DropEnumType { name :: Text } -- | CREATE EXTENSION IF NOT EXISTS "name"; | CreateExtension { name :: Text, ifNotExists :: Bool } -- | ALTER TABLE tableName ADD CONSTRAINT constraint; | AddConstraint { tableName :: Text, constraint :: Constraint, deferrable :: Maybe Bool, deferrableType :: Maybe DeferrableType } -- | ALTER TABLE tableName DROP CONSTRAINT constraintName; | DropConstraint { tableName, constraintName :: Text } -- | ALTER TABLE tableName ADD COLUMN column; | AddColumn { tableName :: Text, column :: Column } -- | ALTER TABLE tableName DROP COLUMN columnName; | DropColumn { tableName :: Text, columnName :: Text } -- | DROP TABLE tableName; | DropTable { tableName :: Text } | UnknownStatement { raw :: Text } | Comment { content :: Text } -- | CREATE INDEX indexName ON tableName (columnName); CREATE INDEX indexName ON tableName (LOWER(columnName)); -- | CREATE UNIQUE INDEX name ON table (column [, ...]); | CreateIndex { indexName :: Text, unique :: Bool, tableName :: Text, columns :: [IndexColumn], whereClause :: Maybe Expression, indexType :: Maybe IndexType } -- | DROP INDEX indexName; | DropIndex { indexName :: Text } -- | CREATE OR REPLACE FUNCTION functionName(param1 TEXT, param2 INT) RETURNS TRIGGER AS $$functionBody$$ language plpgsql; | CreateFunction { functionName :: Text, functionArguments :: [(Text, PostgresType)], functionBody :: Text, orReplace :: Bool, returns :: PostgresType, language :: Text } -- | ALTER TABLE tableName ENABLE ROW LEVEL SECURITY; | EnableRowLevelSecurity { tableName :: Text } -- CREATE POLICY name ON tableName USING using WITH CHECK check; | CreatePolicy { name :: Text, tableName :: Text, action :: Maybe PolicyAction, using :: Maybe Expression, check :: Maybe Expression } -- SET name = value; | Set { name :: Text, value :: Expression } -- SELECT query; | SelectStatement { query :: Text } -- CREATE SEQUENCE name; | CreateSequence { name :: Text } -- ALTER TABLE tableName RENAME COLUMN from TO to; | RenameColumn { tableName :: Text, from :: Text, to :: Text } -- ALTER TYPE enumName ADD VALUE newValue; | AddValueToEnumType { enumName :: Text, newValue :: Text, ifNotExists :: Bool } -- ALTER TABLE tableName ALTER COLUMN columnName DROP NOT NULL; | DropNotNull { tableName :: Text, columnName :: Text } -- ALTER TABLE tableName ALTER COLUMN columnName SET NOT NULL; | SetNotNull { tableName :: Text, columnName :: Text } -- | ALTER TABLE from RENAME TO to; | RenameTable { from :: Text, to :: Text } -- | DROP POLICY policyName ON tableName; | DropPolicy { tableName :: Text, policyName :: Text } -- ALTER TABLE tableName ALTER COLUMN columnName SET DEFAULT 'value'; | SetDefaultValue { tableName :: Text, columnName :: Text, value :: Expression } -- ALTER TABLE tableName ALTER COLUMN columnName DROP DEFAULT; | DropDefaultValue { tableName :: Text, columnName :: Text } -- | CREATE TRIGGER ..; | CreateTrigger { name :: !Text, eventWhen :: !TriggerEventWhen, event :: !TriggerEvent, tableName :: !Text, for :: !TriggerFor, whenCondition :: Maybe Expression, functionName :: !Text, arguments :: ![Expression] } -- | CREATE EVENT TRIGGER ..; | CreateEventTrigger { name :: !Text, eventOn :: !Text, whenCondition :: Maybe Expression, functionName :: !Text, arguments :: ![Expression] } -- | DROP TRIGGER .. ON ..; | DropTrigger { name :: !Text, tableName :: !Text } -- | DROP EVENT TRIGGER ..; | DropEventTrigger { name :: !Text } -- | BEGIN; | Begin -- | COMMIT; | Commit | DropFunction { functionName :: !Text } deriving (Eq, Show) data DeferrableType = InitiallyImmediate | InitiallyDeferred deriving (Eq, Show) data CreateTable = CreateTable { name :: Text , columns :: [Column] , primaryKeyConstraint :: PrimaryKeyConstraint , constraints :: [Constraint] , unlogged :: !Bool } deriving (Eq, Show) data Column = Column { name :: Text , columnType :: PostgresType , defaultValue :: Maybe Expression , notNull :: Bool , isUnique :: Bool , generator :: Maybe ColumnGenerator } deriving (Eq, Show) data OnDelete = NoAction | Restrict | SetNull | SetDefault | Cascade deriving (Show, Eq) data ColumnGenerator = ColumnGenerator { generate :: !Expression , stored :: !Bool } deriving (Show, Eq) newtype PrimaryKeyConstraint = PrimaryKeyConstraint { primaryKeyColumnNames :: [Text] } deriving (Eq, Show) data Constraint -- | FOREIGN KEY (columnName) REFERENCES referenceTable (referenceColumn) ON DELETE onDelete; = ForeignKeyConstraint { name :: !(Maybe Text) , columnName :: !Text , referenceTable :: !Text , referenceColumn :: !(Maybe Text) , onDelete :: !(Maybe OnDelete) } | UniqueConstraint { name :: !(Maybe Text) , columnNames :: ![Text] } | CheckConstraint { name :: !(Maybe Text) , checkExpression :: !Expression } | ExcludeConstraint { name :: !(Maybe Text) , excludeElements :: ![ExcludeConstraintElement] , predicate :: !(Maybe Expression) , indexType :: !(Maybe IndexType) } | AlterTableAddPrimaryKey { name :: !(Maybe Text) , primaryKeyConstraint :: !PrimaryKeyConstraint } deriving (Eq, Show) data ExcludeConstraintElement = ExcludeConstraintElement { element :: !Text, operator :: !Text } deriving (Eq, Show) data Expression = -- | Sql string like @'hello'@ TextExpression Text -- | Simple variable like @users@ | VarExpression Text -- | Simple call, like @COALESCE(name, 'unknown name')@ | CallExpression Text [Expression] -- | Not equal operator, a <> b | NotEqExpression Expression Expression -- | Equal operator, a = b | EqExpression Expression Expression -- | a AND b | AndExpression Expression Expression -- | a IS b | IsExpression Expression Expression -- | a IN b | InExpression Expression Expression -- | ('a', 'b') | InArrayExpression [Expression] -- | NOT a | NotExpression Expression -- | EXISTS a | ExistsExpression Expression -- | a OR b | OrExpression Expression Expression -- | a < b | LessThanExpression Expression Expression -- | a <= b | LessThanOrEqualToExpression Expression Expression -- | a > b | GreaterThanExpression Expression Expression -- | a >= b | GreaterThanOrEqualToExpression Expression Expression -- | Double literal value, e.g. 0.1337 | DoubleExpression Double -- | Integer literal value, e.g. 1337 | IntExpression Int -- | value::type | TypeCastExpression Expression PostgresType | SelectExpression Select | DotExpression Expression Text | ConcatenationExpression Expression Expression -- ^ a || b deriving (Eq, Show) data Select = Select { columns :: [Expression] , from :: Expression , alias :: Maybe Text , whereClause :: Expression } deriving (Eq, Show) data PostgresType = PUUID | PText | PInt | PSmallInt | PBigInt | PBoolean | PTimestampWithTimezone | PTimestamp | PReal | PDouble | PPoint | PPolygon | PDate | PBinary | PTime | PInterval { fields :: Maybe Text } | PNumeric { precision :: Maybe Int, scale :: Maybe Int } | PVaryingN (Maybe Int) | PCharacterN Int | PSingleChar | PSerial | PBigserial | PJSONB | PInet | PTSVector | PArray PostgresType | PTrigger | PEventTrigger | PCustomType Text deriving (Eq, Show) data TriggerEventWhen = Before | After | InsteadOf deriving (Eq, Show) data TriggerEvent = TriggerOnInsert | TriggerOnUpdate | TriggerOnDelete | TriggerOnTruncate deriving (Eq, Show) data TriggerFor = ForEachRow | ForEachStatement deriving (Eq, Show) data PolicyAction = PolicyForAll | PolicyForSelect | PolicyForInsert | PolicyForUpdate | PolicyForDelete deriving (Eq, Show) data IndexType = Btree | Gin | Gist deriving (Eq, Show) data IndexColumn = IndexColumn { column :: Expression, columnOrder :: [IndexColumnOrder] } deriving (Eq, Show) data IndexColumnOrder = Asc | Desc | NullsFirst | NullsLast deriving (Eq, Show)