ringo/ringo/src/Ringo/Extractor/Internal.hs

122 lines
4.8 KiB
Haskell
Raw Normal View History

2016-01-01 20:57:54 +05:30
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Ringo.Extractor.Internal where
import qualified Data.Map as Map
import qualified Data.Text as Text
import Prelude.Compat
import Control.Monad.Reader (Reader, asks)
2015-12-16 16:57:10 +05:30
import Data.Function (on)
import Data.Maybe (mapMaybe, fromMaybe, fromJust, catMaybes)
import Data.Monoid ((<>))
2015-12-30 12:21:41 +05:30
import Data.List (nub, nubBy, find)
import Data.Text (Text)
import Ringo.Types.Internal
import Ringo.Utils
2015-12-30 12:21:41 +05:30
findTable :: TableName -> [Table] -> Maybe Table
findTable tName = find ((== tName) . tableName)
findFact :: TableName -> [Fact] -> Maybe Fact
findFact fName = find ((== fName) . factName)
findColumn :: ColumnName -> [Column] -> Maybe Column
findColumn cName = find ((== cName) . columnName)
dimColumnName :: Text -> ColumnName -> ColumnName
2015-12-16 03:03:47 +05:30
dimColumnName dimName columnName =
fromMaybe columnName . Text.stripPrefix (dimName <> "_") $ columnName
dimColumnMapping :: Text -> Fact -> TableName -> [(ColumnName, ColumnName)]
dimColumnMapping dimPrefix fact dimTableName =
[ (dimColumnName factColTargetTable factColTargetColumn, factColTargetColumn)
| FactColumn { factColType = DimVal {..}, ..} <- factColumns fact
, dimPrefix <> factColTargetTable == dimTableName ]
dimColumnMappings :: Text -> Fact -> [(TableName, [(ColumnName, ColumnName)])]
dimColumnMappings dimPrefix fact =
nub [ (dimTableName, dimColumnMapping dimPrefix fact dimTableName)
| FactColumn { factColType = DimVal {..}, ..} <- factColumns fact
, let dimTableName = dimPrefix <> factColTargetTable ]
timeUnitColumnName :: Text -> ColumnName -> TimeUnit -> ColumnName
timeUnitColumnName dimIdColName colName timeUnit =
colName <> "_" <> timeUnitName timeUnit <> "_" <> dimIdColName
2015-12-16 16:57:10 +05:30
factDimFKIdColumnName :: Text -> Text -> Fact -> Table -> [Table] -> ColumnName
factDimFKIdColumnName dimPrefix dimIdColName dimFact dimTable@Table { .. } tables =
if dimTable `elem` tables
then head [ factColTargetColumn
| FactColumn {factColType = DimId {..}, ..} <- factColumns dimFact
, factColTargetTable == tableName ]
else fromMaybe tableName (Text.stripPrefix dimPrefix tableName) <> "_" <> dimIdColName
2015-12-16 16:57:10 +05:30
extractedFactTableName :: Text -> Text -> TableName -> TimeUnit -> TableName
extractedFactTableName factPrefix factInfix factName timeUnit =
factPrefix <> factName <> factInfix <> timeUnitName timeUnit
2015-12-16 16:57:10 +05:30
idColTypeToFKIdColType :: Text -> Text
idColTypeToFKIdColType typ = case Text.toLower typ of
"serial" -> "integer"
"smallserial" -> "smallint"
"bigserial" -> "bigint"
_ -> typ
2015-12-16 16:57:10 +05:30
2015-12-16 03:03:47 +05:30
extractDimensionTables :: Fact -> Reader Env [Table]
extractDimensionTables fact = do
settings <- asks envSettings
2015-12-16 03:03:47 +05:30
tables <- asks envTables
return $ dimTablesFromIds tables fact ++ dimTablesFromVals settings tables fact
dimTablesFromIds :: [Table] -> Fact -> [Table]
dimTablesFromIds tables fact =
catMaybes [ findTable factColTargetTable tables
| FactColumn { factColType = DimId {..} } <- factColumns fact ]
dimTablesFromVals :: Settings -> [Table] -> Fact -> [Table]
dimTablesFromVals Settings {..} tables fact =
fact
>>- factColumns
>>> mapMaybe (findDimValColumn . Just)
>>> Map.fromListWith (flip (++))
>>> Map.mapWithKey makeDimColumns
>>> Map.toList
>>> map (uncurry makeDimTable)
where
Table {..} = fromJust . findTable (factTableName fact) $ tables
makeDimTable dim cols =
Table { tableName = settingDimPrefix <> dim
, tableColumns =
Column settingDimTableIdColumnName settingDimTableIdColumnType NotNull : cols
, tableConstraints = [ PrimaryKey settingDimTableIdColumnName
, UniqueKey (map columnName cols)
]
}
makeDimColumns dim cols = [ col { columnName = dimColumnName dim (columnName col)
, columnNullable = NotNull
}
| col <- nub cols
]
findDimValColumn :: Maybe FactColumn -> Maybe (TableName, [Column])
findDimValColumn fcol = do
FactColumn { factColType = DimVal {..}, .. } <- fcol
column <- findColumn factColTargetColumn tableColumns
return (factColTargetTable, [column])
2015-12-16 16:57:10 +05:30
extractAllDimensionTables :: Fact -> Reader Env [(Fact, Table)]
2015-12-16 03:03:47 +05:30
extractAllDimensionTables fact = do
2015-12-16 16:57:10 +05:30
myDims <- map (fact,) <$> extractDimensionTables fact
parentDims <- concat <$> mapM extract (factParentNames fact)
2015-12-16 16:57:10 +05:30
return . nubBy ((==) `on` snd) $ myDims ++ parentDims
where
extract fName = asks envFacts >>= extractAllDimensionTables . fromJust . findFact fName