2016-02-05 16:17:57 +05:30
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
|
|
|
{-# LANGUAGE GADTs #-}
|
|
|
|
{-# LANGUAGE Rank2Types #-}
|
|
|
|
{-# LANGUAGE StandaloneDeriving #-}
|
2016-06-22 17:58:46 +05:30
|
|
|
{-# LANGUAGE DataKinds #-}
|
|
|
|
{-# LANGUAGE KindSignatures #-}
|
2016-02-05 16:17:57 +05:30
|
|
|
|
|
|
|
module Ringo.Types.Internal where
|
|
|
|
|
|
|
|
import qualified Data.Text as Text
|
|
|
|
|
|
|
|
import Data.Map (Map)
|
|
|
|
import Data.Monoid ((<>))
|
|
|
|
import Data.Text (Text)
|
|
|
|
|
|
|
|
showColNames :: [Text] -> String
|
|
|
|
showColNames cols = Text.unpack $ "(" <> Text.intercalate ", " cols <> ")"
|
|
|
|
|
|
|
|
type ColumnName = Text
|
|
|
|
type ColumnType = Text
|
|
|
|
type TableName = Text
|
|
|
|
|
|
|
|
data Nullable = Null | NotNull deriving (Eq, Enum)
|
|
|
|
|
|
|
|
instance Show Nullable where
|
|
|
|
show Null = "NULL"
|
|
|
|
show NotNull = "NOT NULL"
|
|
|
|
|
|
|
|
data Column = Column
|
|
|
|
{ columnName :: !ColumnName
|
|
|
|
, columnType :: !ColumnType
|
|
|
|
, columnNullable :: !Nullable
|
|
|
|
} deriving (Eq)
|
|
|
|
|
|
|
|
instance Show Column where
|
|
|
|
show Column {..} = "Column "
|
|
|
|
++ Text.unpack columnName ++ " "
|
|
|
|
++ Text.unpack columnType ++ " "
|
|
|
|
++ show columnNullable
|
|
|
|
|
|
|
|
data TableConstraint = PrimaryKey !ColumnName
|
|
|
|
| UniqueKey ![ColumnName]
|
|
|
|
| ForeignKey !TableName ![(ColumnName, ColumnName)]
|
|
|
|
deriving (Eq)
|
|
|
|
|
|
|
|
instance Show TableConstraint where
|
|
|
|
show (PrimaryKey col) = "PrimaryKey " ++ Text.unpack col
|
|
|
|
show (UniqueKey cols) = "UniqueKey " ++ showColNames cols
|
|
|
|
show (ForeignKey tName colMap) = "ForeignKey " ++ showColNames (map fst colMap) ++ " "
|
|
|
|
++ Text.unpack tName ++ " " ++ showColNames (map snd colMap)
|
|
|
|
data Table = Table
|
|
|
|
{ tableName :: !TableName
|
|
|
|
, tableColumns :: ![Column]
|
|
|
|
, tableConstraints :: ![TableConstraint]
|
|
|
|
} deriving (Eq)
|
|
|
|
|
|
|
|
instance Show Table where
|
|
|
|
show Table {..} =
|
|
|
|
unlines $ ("Table " ++ Text.unpack tableName) : map show tableColumns ++ map show tableConstraints
|
|
|
|
|
|
|
|
data TimeUnit = Second | Minute | Hour | Day | Week
|
|
|
|
deriving (Eq, Enum, Show, Read)
|
|
|
|
|
|
|
|
timeUnitName :: TimeUnit -> Text
|
|
|
|
timeUnitName = Text.toLower . Text.pack . show
|
|
|
|
|
|
|
|
timeUnitToSeconds :: TimeUnit -> Int
|
|
|
|
timeUnitToSeconds Second = 1
|
|
|
|
timeUnitToSeconds Minute = 60 * timeUnitToSeconds Second
|
|
|
|
timeUnitToSeconds Hour = 60 * timeUnitToSeconds Minute
|
|
|
|
timeUnitToSeconds Day = 24 * timeUnitToSeconds Hour
|
|
|
|
timeUnitToSeconds Week = 7 * timeUnitToSeconds Day
|
|
|
|
|
|
|
|
data Fact = Fact
|
|
|
|
{ factName :: !TableName
|
|
|
|
, factTableName :: !TableName
|
|
|
|
, factTablePersistent :: !Bool
|
|
|
|
, factParentNames :: ![TableName]
|
|
|
|
, factColumns :: ![FactColumn]
|
|
|
|
} deriving (Show)
|
|
|
|
|
2016-06-22 17:58:46 +05:30
|
|
|
data FactColumnKind = FCKNone | FCKTargetTable | FCKMaybeSourceColumn | FCKSourceColumn
|
|
|
|
|
|
|
|
data FactColumnType (a :: FactColumnKind) where
|
|
|
|
DimTime :: FactColumnType 'FCKNone
|
|
|
|
NoDimId :: FactColumnType 'FCKNone
|
|
|
|
TenantId :: FactColumnType 'FCKNone
|
|
|
|
DimId :: { factColTargetTable :: !TableName } -> FactColumnType 'FCKTargetTable
|
|
|
|
DimVal :: { factColTargetTable :: !TableName } -> FactColumnType 'FCKTargetTable
|
|
|
|
FactCount :: { factColMaybeSourceColumn :: !(Maybe ColumnName) } -> FactColumnType 'FCKMaybeSourceColumn
|
|
|
|
FactCountDistinct :: { factColMaybeSourceColumn :: !(Maybe ColumnName) } -> FactColumnType 'FCKMaybeSourceColumn
|
|
|
|
FactSum :: { factColSourceColumn :: !ColumnName } -> FactColumnType 'FCKSourceColumn
|
|
|
|
FactAverage :: { factColSourceColumn :: !ColumnName } -> FactColumnType 'FCKSourceColumn
|
|
|
|
FactMax :: { factColSourceColumn :: !ColumnName } -> FactColumnType 'FCKSourceColumn
|
|
|
|
FactMin :: { factColSourceColumn :: !ColumnName } -> FactColumnType 'FCKSourceColumn
|
2016-02-05 16:17:57 +05:30
|
|
|
|
|
|
|
deriving instance Show (FactColumnType a)
|
|
|
|
|
|
|
|
data FactColumn = forall a. FactColumn
|
|
|
|
{ factColTargetColumn :: !ColumnName
|
|
|
|
, factColType :: FactColumnType a }
|
|
|
|
|
|
|
|
deriving instance Show FactColumn
|
|
|
|
|
|
|
|
factSourceColumnName :: FactColumn -> Maybe ColumnName
|
|
|
|
factSourceColumnName FactColumn {..} = case factColType of
|
|
|
|
DimTime -> Just factColTargetColumn
|
|
|
|
NoDimId -> Just factColTargetColumn
|
|
|
|
TenantId -> Just factColTargetColumn
|
|
|
|
DimId {..} -> Just factColTargetColumn
|
|
|
|
DimVal {..} -> Just factColTargetColumn
|
|
|
|
FactCount {..} -> factColMaybeSourceColumn
|
|
|
|
FactCountDistinct {..} -> factColMaybeSourceColumn
|
|
|
|
FactSum {..} -> Just factColSourceColumn
|
|
|
|
FactAverage {..} -> Just factColSourceColumn
|
|
|
|
FactMax {..} -> Just factColSourceColumn
|
|
|
|
FactMin {..} -> Just factColSourceColumn
|
|
|
|
|
|
|
|
data Settings = Settings
|
|
|
|
{ settingDimPrefix :: !Text
|
|
|
|
, settingFactPrefix :: !Text
|
|
|
|
, settingTimeUnit :: !TimeUnit
|
|
|
|
, settingAvgCountColumSuffix :: !Text
|
|
|
|
, settingAvgSumColumnSuffix :: !Text
|
|
|
|
, settingDimTableIdColumnName :: !Text
|
|
|
|
, settingDimTableIdColumnType :: !Text
|
|
|
|
, settingFactCountColumnType :: !Text
|
|
|
|
, settingFactCountDistinctErrorRate :: !Double
|
|
|
|
, settingFactInfix :: !Text
|
|
|
|
, settingDependenciesJSONFileName :: !Text
|
|
|
|
, settingFactsJSONFileName :: !Text
|
|
|
|
, settingDimensionJSONFileName :: !Text
|
|
|
|
, settingForeignKeyIdCoalesceValue :: !Int
|
|
|
|
, settingTableNameSuffixTemplate :: !Text
|
|
|
|
} deriving (Eq, Show)
|
|
|
|
|
|
|
|
defSettings :: Settings
|
|
|
|
defSettings = Settings
|
|
|
|
{ settingDimPrefix = "dim_"
|
|
|
|
, settingFactPrefix = "fact_"
|
|
|
|
, settingTimeUnit = Minute
|
|
|
|
, settingAvgCountColumSuffix = "_count"
|
|
|
|
, settingAvgSumColumnSuffix = "_sum"
|
|
|
|
, settingDimTableIdColumnName = "id"
|
|
|
|
, settingDimTableIdColumnType = "serial"
|
|
|
|
, settingFactCountColumnType = "integer"
|
|
|
|
, settingFactCountDistinctErrorRate = 0.05
|
|
|
|
, settingFactInfix = "_by_"
|
|
|
|
, settingDependenciesJSONFileName = "dependencies.json"
|
|
|
|
, settingFactsJSONFileName = "facts.json"
|
|
|
|
, settingDimensionJSONFileName = "dimensions.json"
|
|
|
|
, settingForeignKeyIdCoalesceValue = -1
|
|
|
|
, settingTableNameSuffixTemplate = "{{suff}}"
|
|
|
|
}
|
|
|
|
|
|
|
|
data ValidationError = MissingTable !TableName
|
|
|
|
| DuplicateTable !TableName
|
|
|
|
| MissingFact !TableName
|
|
|
|
| DuplicateFact !TableName
|
|
|
|
| MissingColumn !TableName !ColumnName
|
|
|
|
| DuplicateColumn !TableName !ColumnName
|
|
|
|
| MissingTimeColumn !TableName
|
2016-06-23 12:29:18 +05:30
|
|
|
| DuplicateDimension !TableName
|
2016-02-05 16:17:57 +05:30
|
|
|
| MissingNotNullConstraint !TableName !ColumnName
|
|
|
|
| MissingTypeDefault !Text
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
type TypeDefaults = Map Text Text
|
|
|
|
|
2016-06-22 17:10:14 +05:30
|
|
|
data Env = Env
|
|
|
|
{ _envTables :: ![Table]
|
|
|
|
, _envFacts :: ![Fact]
|
|
|
|
, _envSettings :: !Settings
|
|
|
|
, _envTypeDefaults :: !TypeDefaults
|
|
|
|
} deriving (Show)
|
2016-02-05 16:17:57 +05:30
|
|
|
|
2016-06-22 17:10:14 +05:30
|
|
|
envTables :: Env -> [Table]
|
|
|
|
envTables = _envTables
|
|
|
|
|
|
|
|
envFacts :: Env -> [Fact]
|
|
|
|
envFacts = _envFacts
|
|
|
|
|
|
|
|
envSettings :: Env -> Settings
|
|
|
|
envSettings = _envSettings
|
2016-02-05 16:17:57 +05:30
|
|
|
|
2016-06-22 17:10:14 +05:30
|
|
|
envTypeDefaults :: Env -> TypeDefaults
|
|
|
|
envTypeDefaults = _envTypeDefaults
|
2016-02-05 16:17:57 +05:30
|
|
|
|
|
|
|
data TablePopulationMode = FullPopulation | IncrementalPopulation deriving (Eq, Show)
|
|
|
|
|
|
|
|
type Dependencies = Map TableName [TableName]
|