Refactoring.
parent
a84325cb2a
commit
c430e5f255
|
@ -5,7 +5,7 @@ module Ringo.Extractor
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Reader (Reader, asks)
|
import Control.Monad.Reader (Reader, asks)
|
||||||
import Data.Maybe (mapMaybe, fromJust)
|
import Data.Maybe (fromJust)
|
||||||
import Data.Monoid ((<>))
|
import Data.Monoid ((<>))
|
||||||
|
|
||||||
import Ringo.Extractor.Internal
|
import Ringo.Extractor.Internal
|
||||||
|
@ -22,8 +22,9 @@ extractFactTable fact = do
|
||||||
dimIdColName = settingDimTableIdColumnName
|
dimIdColName = settingDimTableIdColumnName
|
||||||
sourceColumnType colName = columnType . fromJust . findColumn colName . tableColumns $ table
|
sourceColumnType colName = columnType . fromJust . findColumn colName . tableColumns $ table
|
||||||
|
|
||||||
columns = flip concatMap (factColumns fact) $ \col -> case col of
|
columns = concatFor (factColumns fact) $ \col -> case col of
|
||||||
DimTime cName -> [ Column (timeUnitColumnName dimIdColName cName settingTimeUnit) "integer" NotNull ]
|
DimTime cName ->
|
||||||
|
[ Column (timeUnitColumnName dimIdColName cName settingTimeUnit) "integer" NotNull ]
|
||||||
NoDimId cName -> [ fromJust . findColumn cName . tableColumns $ table]
|
NoDimId cName -> [ fromJust . findColumn cName . tableColumns $ table]
|
||||||
FactCount cName -> [ Column cName countColType NotNull ]
|
FactCount cName -> [ Column cName countColType NotNull ]
|
||||||
FactSum scName cName -> [ Column cName (sourceColumnType scName) NotNull ]
|
FactSum scName cName -> [ Column cName (sourceColumnType scName) NotNull ]
|
||||||
|
@ -35,22 +36,22 @@ extractFactTable fact = do
|
||||||
[ Column (cName <> settingCountDistinctColumSuffix) (countColType <> "[]") NotNull ]
|
[ Column (cName <> settingCountDistinctColumSuffix) (countColType <> "[]") NotNull ]
|
||||||
_ -> []
|
_ -> []
|
||||||
|
|
||||||
fks = flip map allDims $ \(_, Table {..}) ->
|
fks = for allDims $ \(_, Table {..}) ->
|
||||||
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
||||||
|
colType = idColTypeToFKIdColType settingDimTableIdColumnType
|
||||||
colNullable = if any ((== Null) . columnNullable) tableColumns then Null else NotNull
|
colNullable = if any ((== Null) . columnNullable) tableColumns then Null else NotNull
|
||||||
in ( Column colName (idColTypeToFKIdColType settingDimTableIdColumnType) colNullable
|
in ( Column colName colType colNullable , ForeignKey tableName [(colName, dimIdColName)] )
|
||||||
, ForeignKey tableName [(colName, dimIdColName)]
|
|
||||||
)
|
|
||||||
|
|
||||||
ukColNames =
|
ukColNames =
|
||||||
(++ map (columnName . fst) fks)
|
(++ map (columnName . fst) fks)
|
||||||
. flip mapMaybe (factColumns fact) $ \col -> case col of
|
. forMaybe (factColumns fact) $ \col -> case col of
|
||||||
DimTime cName -> Just (timeUnitColumnName dimIdColName cName settingTimeUnit)
|
DimTime cName -> Just (timeUnitColumnName dimIdColName cName settingTimeUnit)
|
||||||
NoDimId cName -> Just cName
|
NoDimId cName -> Just cName
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
return Table { tableName =
|
return Table
|
||||||
extractedFactTableName settingFactPrefix settingFactInfix (factName fact) settingTimeUnit
|
{ tableName =
|
||||||
, tableColumns = columns ++ map fst fks
|
extractedFactTableName settingFactPrefix settingFactInfix (factName fact) settingTimeUnit
|
||||||
, tableConstraints = UniqueKey ukColNames : map snd fks
|
, tableColumns = columns ++ map fst fks
|
||||||
}
|
, tableConstraints = UniqueKey ukColNames : map snd fks
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ extractDimensionTables fact = do
|
||||||
return $ dimsFromIds tables ++ dimsFromVals settings (tableColumns table)
|
return $ dimsFromIds tables ++ dimsFromVals settings (tableColumns table)
|
||||||
where
|
where
|
||||||
dimsFromIds tables =
|
dimsFromIds tables =
|
||||||
flip mapMaybe (factColumns fact) $ \fcol -> case fcol of
|
forMaybe (factColumns fact) $ \fcol -> case fcol of
|
||||||
DimId d _ -> findTable d tables
|
DimId d _ -> findTable d tables
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
|
@ -63,9 +63,8 @@ extractDimensionTables fact = do
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
. Map.toList
|
. Map.toList
|
||||||
. Map.mapWithKey (\dim ->
|
. Map.mapWithKey
|
||||||
map (\col@Column {..} -> col { columnName = dimColumnName dim columnName })
|
(\dim -> map (\col -> col { columnName = dimColumnName dim (columnName col) }) . nub)
|
||||||
. nub)
|
|
||||||
. Map.fromListWith (flip (++))
|
. Map.fromListWith (flip (++))
|
||||||
. mapMaybe (\fcol -> do
|
. mapMaybe (\fcol -> do
|
||||||
DimVal d col <- fcol
|
DimVal d col <- fcol
|
||||||
|
|
|
@ -56,21 +56,22 @@ factTableDefnSQL fact table = do
|
||||||
Settings {..} <- asks envSettings
|
Settings {..} <- asks envSettings
|
||||||
allDims <- extractAllDimensionTables fact
|
allDims <- extractAllDimensionTables fact
|
||||||
|
|
||||||
let factCols = flip mapMaybe (factColumns fact) $ \col -> case col of
|
let factCols = forMaybe (factColumns fact) $ \col -> case col of
|
||||||
DimTime cName -> Just $ timeUnitColumnName settingDimTableIdColumnName cName settingTimeUnit
|
DimTime cName -> Just $ timeUnitColumnName settingDimTableIdColumnName cName settingTimeUnit
|
||||||
NoDimId cName -> Just cName
|
NoDimId cName -> Just cName
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
dimCols = flip map allDims $ \(_, Table {..}) ->
|
dimCols = [ factDimFKIdColumnName settingDimPrefix settingDimTableIdColumnName tableName
|
||||||
factDimFKIdColumnName settingDimPrefix settingDimTableIdColumnName tableName
|
| (_, Table {..}) <- allDims ]
|
||||||
|
|
||||||
|
indexSQLs = [ "CREATE INDEX ON " <> tableName table <> " USING btree (" <> col <> ")"
|
||||||
|
| col <- factCols ++ dimCols ]
|
||||||
|
|
||||||
indexSQLs = flip map (factCols ++ dimCols) $ \col ->
|
|
||||||
"CREATE INDEX ON " <> tableName table <> " USING btree (" <> col <> ")"
|
|
||||||
return $ tableDefnSQL table ++ indexSQLs
|
return $ tableDefnSQL table ++ indexSQLs
|
||||||
|
|
||||||
dimColumnMapping :: Text -> Fact -> TableName -> [(ColumnName, ColumnName)]
|
dimColumnMapping :: Text -> Fact -> TableName -> [(ColumnName, ColumnName)]
|
||||||
dimColumnMapping dimPrefix fact dimTableName =
|
dimColumnMapping dimPrefix fact dimTableName =
|
||||||
flip mapMaybe (factColumns fact) $ \fCol -> case fCol of
|
forMaybe (factColumns fact) $ \fCol -> case fCol of
|
||||||
DimVal dName cName | dimPrefix <> dName == dimTableName ->
|
DimVal dName cName | dimPrefix <> dName == dimTableName ->
|
||||||
Just (dimColumnName dName cName, cName)
|
Just (dimColumnName dName cName, cName)
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
@ -88,19 +89,19 @@ dimensionTableInsertSQL fact dimTableName = do
|
||||||
|
|
||||||
factTableInsertSQL :: Fact -> Reader Env Text
|
factTableInsertSQL :: Fact -> Reader Env Text
|
||||||
factTableInsertSQL fact = do
|
factTableInsertSQL fact = do
|
||||||
let fTableName = factTableName fact
|
|
||||||
Settings {..} <- asks envSettings
|
Settings {..} <- asks envSettings
|
||||||
allDims <- extractAllDimensionTables fact
|
allDims <- extractAllDimensionTables fact
|
||||||
tables <- asks envTables
|
tables <- asks envTables
|
||||||
let table = fromJust . findTable fTableName $ tables
|
let fTableName = factTableName fact
|
||||||
|
table = fromJust . findTable fTableName $ tables
|
||||||
dimIdColName = settingDimTableIdColumnName
|
dimIdColName = settingDimTableIdColumnName
|
||||||
|
|
||||||
let timeUnitColumnInsertSQL cName =
|
timeUnitColumnInsertSQL cName =
|
||||||
let colName = timeUnitColumnName dimIdColName cName settingTimeUnit
|
let colName = timeUnitColumnName dimIdColName cName settingTimeUnit
|
||||||
in (colName, "floor(extract(epoch from " <> fullColName fTableName cName <> ")/"
|
in (colName, "floor(extract(epoch from " <> fullColName fTableName cName <> ")/"
|
||||||
<> Text.pack (show $ timeUnitToSeconds settingTimeUnit) <> ")")
|
<> Text.pack (show $ timeUnitToSeconds settingTimeUnit) <> ")")
|
||||||
|
|
||||||
factColMap = flip concatMap (factColumns fact) $ \col -> case col of
|
factColMap = concatFor (factColumns fact) $ \col -> case col of
|
||||||
DimTime cName -> [ timeUnitColumnInsertSQL cName ]
|
DimTime cName -> [ timeUnitColumnInsertSQL cName ]
|
||||||
NoDimId cName -> [ (cName, fullColName fTableName cName) ]
|
NoDimId cName -> [ (cName, fullColName fTableName cName) ]
|
||||||
FactCount cName -> [ (cName, "count(*)") ]
|
FactCount cName -> [ (cName, "count(*)") ]
|
||||||
|
@ -111,22 +112,20 @@ factTableInsertSQL fact = do
|
||||||
, "sum(" <> fullColName fTableName scName <> ")") ]
|
, "sum(" <> fullColName fTableName scName <> ")") ]
|
||||||
_ -> []
|
_ -> []
|
||||||
|
|
||||||
dimColMap = flip map allDims $ \(dimFact, factTable@Table {..}) ->
|
dimColMap = for allDims $ \(dimFact, factTable@Table {..}) ->
|
||||||
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
||||||
factSourceTableName = factTableName dimFact
|
factSourceTableName = factTableName dimFact
|
||||||
insertSQL =
|
insertSQL = if factTable `elem` tables
|
||||||
if factTable `elem` tables
|
then fullColName factSourceTableName colName
|
||||||
then fullColName factSourceTableName colName
|
else let
|
||||||
else
|
dimLookupWhereClauses =
|
||||||
let dimLookupWhereClauses =
|
[ fullColName tableName c1 <> " = " <> fullColName factSourceTableName c2
|
||||||
map (\(c1, c2) ->
|
| (c1, c2) <- dimColumnMapping settingDimPrefix dimFact tableName ]
|
||||||
fullColName tableName c1 <> " = " <> fullColName factSourceTableName c2)
|
|
||||||
$ dimColumnMapping settingDimPrefix dimFact tableName
|
|
||||||
in "SELECT " <> dimIdColName <> " FROM " <> tableName <> "\nWHERE "
|
in "SELECT " <> dimIdColName <> " FROM " <> tableName <> "\nWHERE "
|
||||||
<> (Text.concat . intersperse "\n AND " $ dimLookupWhereClauses)
|
<> (Text.concat . intersperse "\n AND " $ dimLookupWhereClauses)
|
||||||
in (colName, insertSQL)
|
in (colName, insertSQL)
|
||||||
|
|
||||||
colMap = map (\(cName, sql) -> (cName, asName cName sql)) $ factColMap ++ dimColMap
|
colMap = [ (cName, asName cName sql) | (cName, sql) <- factColMap ++ dimColMap ]
|
||||||
|
|
||||||
joinClauses =
|
joinClauses =
|
||||||
mapMaybe (\tName -> (\p -> "LEFT JOIN " <> tName <> " ON "<> p) <$> joinClausePreds table tName)
|
mapMaybe (\tName -> (\p -> "LEFT JOIN " <> tName <> " ON "<> p) <$> joinClausePreds table tName)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module Ringo.Utils where
|
module Ringo.Utils where
|
||||||
|
|
||||||
import Data.List (find)
|
import Data.Maybe (mapMaybe)
|
||||||
|
import Data.List (find)
|
||||||
|
|
||||||
import Ringo.Types
|
import Ringo.Types
|
||||||
|
|
||||||
|
@ -12,3 +13,17 @@ findFact fName = find ((== fName) . factName)
|
||||||
|
|
||||||
findColumn :: ColumnName -> [Column] -> Maybe Column
|
findColumn :: ColumnName -> [Column] -> Maybe Column
|
||||||
findColumn cName = find ((== cName) . columnName)
|
findColumn cName = find ((== cName) . columnName)
|
||||||
|
|
||||||
|
for :: [a] -> (a -> b) -> [b]
|
||||||
|
for = flip map
|
||||||
|
|
||||||
|
forMaybe :: [a] -> (a -> Maybe b) -> [b]
|
||||||
|
forMaybe = flip mapMaybe
|
||||||
|
|
||||||
|
#if MIN_VERSION_base(4,8,0)
|
||||||
|
concatFor :: (Foldable t) => t a -> (a -> [b]) -> [b]
|
||||||
|
concatFor = flip concatMap
|
||||||
|
#else
|
||||||
|
concatFor :: [a] -> (a -> [b]) -> [b]
|
||||||
|
concatFor = flip concatMap
|
||||||
|
#endif
|
||||||
|
|
|
@ -46,7 +46,7 @@ validateFact Fact {..} = do
|
||||||
return $ tableVs ++ parentVs ++ colVs
|
return $ tableVs ++ parentVs ++ colVs
|
||||||
where
|
where
|
||||||
checkFactParents fName = do
|
checkFactParents fName = do
|
||||||
facts <- asks envFacts
|
facts <- asks envFacts
|
||||||
case findFact fName facts of
|
case findFact fName facts of
|
||||||
Nothing -> return [ MissingFact fName ]
|
Nothing -> return [ MissingFact fName ]
|
||||||
Just pFact -> validateFact pFact
|
Just pFact -> validateFact pFact
|
||||||
|
@ -56,12 +56,8 @@ validateFact Fact {..} = do
|
||||||
++ checkColumnTable tables factCol
|
++ checkColumnTable tables factCol
|
||||||
|
|
||||||
checkColumnTable tables factCol = case factCol of
|
checkColumnTable tables factCol = case factCol of
|
||||||
DimId tName _ -> go tName
|
DimId tName _ -> maybe [ MissingTable tName ] (const []) $ findTable tName tables
|
||||||
_ -> []
|
_ -> []
|
||||||
where
|
|
||||||
go tName = case findTable tName tables of
|
|
||||||
Nothing -> [ MissingTable tName ]
|
|
||||||
Just _ -> []
|
|
||||||
|
|
||||||
withFactValidation :: Fact -> Reader Env a -> Reader Env (Either [ValidationError] a)
|
withFactValidation :: Fact -> Reader Env a -> Reader Env (Either [ValidationError] a)
|
||||||
withFactValidation fact func = do
|
withFactValidation fact func = do
|
||||||
|
|
Loading…
Reference in New Issue