Fixes bugs in fact table DDL and insert SQL generation.
parent
4a07d0c828
commit
f8a6382aa3
|
@ -16,7 +16,8 @@ extractFactTable :: Fact -> Reader Env Table
|
||||||
extractFactTable fact = do
|
extractFactTable fact = do
|
||||||
Settings {..} <- asks envSettings
|
Settings {..} <- asks envSettings
|
||||||
allDims <- extractAllDimensionTables fact
|
allDims <- extractAllDimensionTables fact
|
||||||
table <- asks $ fromJust . findTable (factTableName fact) . envTables
|
tables <- asks envTables
|
||||||
|
let table = fromJust . findTable (factTableName fact) $ tables
|
||||||
|
|
||||||
let countColType = settingFactCountColumnType
|
let countColType = settingFactCountColumnType
|
||||||
dimIdColName = settingDimTableIdColumnName
|
dimIdColName = settingDimTableIdColumnName
|
||||||
|
@ -36,10 +37,13 @@ extractFactTable fact = do
|
||||||
[ Column (cName <> settingCountDistinctColumSuffix) (countColType <> "[]") NotNull ]
|
[ Column (cName <> settingCountDistinctColumSuffix) (countColType <> "[]") NotNull ]
|
||||||
_ -> []
|
_ -> []
|
||||||
|
|
||||||
fks = for allDims $ \(_, Table {..}) ->
|
fks = for allDims $ \(fact', tab@Table {..}) ->
|
||||||
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
let colName = factDimFKIdColumnName settingDimPrefix dimIdColName tableName
|
||||||
colType = idColTypeToFKIdColType settingDimTableIdColumnType
|
colType = idColTypeToFKIdColType settingDimTableIdColumnType
|
||||||
colNullable = if any ((== Null) . columnNullable) tableColumns then Null else NotNull
|
colNullable =
|
||||||
|
if tab `elem` tables || fact /= fact' || any ((== Null) . columnNullable) tableColumns
|
||||||
|
then Null
|
||||||
|
else NotNull
|
||||||
in ( Column colName colType colNullable , ForeignKey tableName [(colName, dimIdColName)] )
|
in ( Column colName colType colNullable , ForeignKey tableName [(colName, dimIdColName)] )
|
||||||
|
|
||||||
ukColNames =
|
ukColNames =
|
||||||
|
|
|
@ -98,18 +98,27 @@ factTableInsertSQL fact = do
|
||||||
|
|
||||||
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
|
||||||
<> Text.pack (show $ timeUnitToSeconds settingTimeUnit) <> ")")
|
, "floor(extract(epoch from " <> fullColName fTableName cName <> ")/"
|
||||||
|
<> Text.pack (show $ timeUnitToSeconds settingTimeUnit) <> ")"
|
||||||
|
, True
|
||||||
|
)
|
||||||
|
|
||||||
factColMap = concatFor (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, True) ]
|
||||||
FactCount cName -> [ (cName, "count(*)") ]
|
FactCount cName -> [ (cName, "count(*)", False) ]
|
||||||
FactSum scName cName -> [ (cName, "sum(" <> fullColName fTableName scName <> ")") ]
|
FactSum scName cName -> [ (cName, "sum(" <> fullColName fTableName scName <> ")", False) ]
|
||||||
FactAverage scName cName -> [ ( cName <> settingAvgCountColumSuffix
|
FactAverage scName cName ->
|
||||||
, "count(" <> fullColName fTableName scName <> ")")
|
[ ( cName <> settingAvgCountColumSuffix
|
||||||
, ( cName <> settingAvgSumColumnSuffix
|
, "count(" <> fullColName fTableName scName <> ")"
|
||||||
, "sum(" <> fullColName fTableName scName <> ")") ]
|
, False
|
||||||
|
)
|
||||||
|
, ( cName <> settingAvgSumColumnSuffix
|
||||||
|
, "sum(" <> fullColName fTableName scName <> ")"
|
||||||
|
, False
|
||||||
|
)
|
||||||
|
]
|
||||||
_ -> []
|
_ -> []
|
||||||
|
|
||||||
dimColMap = for allDims $ \(dimFact, factTable@Table {..}) ->
|
dimColMap = for allDims $ \(dimFact, factTable@Table {..}) ->
|
||||||
|
@ -123,26 +132,29 @@ factTableInsertSQL fact = do
|
||||||
| (c1, c2) <- dimColumnMapping settingDimPrefix dimFact tableName ]
|
| (c1, 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, True)
|
||||||
|
|
||||||
colMap = [ (cName, asName cName sql) | (cName, sql) <- factColMap ++ dimColMap ]
|
colMap = [ (cName, if addAs then asName cName sql else sql, addAs)
|
||||||
|
| (cName, sql, addAs) <- 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)
|
||||||
. nub
|
. nub
|
||||||
. map (\(dimFact, _) -> factTableName dimFact)
|
. map (factTableName . fst)
|
||||||
$ allDims
|
$ allDims
|
||||||
|
|
||||||
return $ "INSERT INTO "
|
return $ "INSERT INTO "
|
||||||
<> extractedFactTableName settingFactPrefix settingFactInfix (factName fact) settingTimeUnit
|
<> extractedFactTableName settingFactPrefix settingFactInfix (factName fact) settingTimeUnit
|
||||||
<> " (\n" <> Text.concat (intersperse ",\n " . map fst $ colMap) <> "\n)"
|
<> " (\n" <> unlineCols (map fst3 colMap) <> "\n)"
|
||||||
<> "\nSELECT \n" <> Text.concat (intersperse ",\n " . map snd $ colMap)
|
<> "\nSELECT \n" <> unlineCols (map snd3 colMap)
|
||||||
<> "\nFROM " <> fTableName <> "\n" <> Text.concat (intersperse "\n" joinClauses)
|
<> "\nFROM " <> fTableName <> "\n" <> Text.concat (intersperse "\n" joinClauses)
|
||||||
<> "\nGROUP BY \n" <> Text.concat (intersperse ",\n " . map fst $ colMap)
|
<> "\nGROUP BY \n"
|
||||||
|
<> unlineCols (map ((groupByColPrefix <>) . fst3) . filter thd3 $ colMap)
|
||||||
where
|
where
|
||||||
|
groupByColPrefix = "xxff_"
|
||||||
fullColName tName cName = tName <> "." <> cName
|
fullColName tName cName = tName <> "." <> cName
|
||||||
|
asName cName sql = "(" <> sql <> ")" <> " as " <> groupByColPrefix <> cName
|
||||||
asName cName sql = "(" <> sql <> ")" <> " as " <> cName
|
unlineCols = Text.concat . intersperse ",\n "
|
||||||
|
|
||||||
joinClausePreds table oTableName =
|
joinClausePreds table oTableName =
|
||||||
fmap (\(ForeignKey _ colPairs) ->
|
fmap (\(ForeignKey _ colPairs) ->
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
module Ringo.Utils where
|
module Ringo.Utils where
|
||||||
|
|
||||||
|
import qualified Control.Arrow as Arrow
|
||||||
|
|
||||||
import Data.Maybe (mapMaybe)
|
import Data.Maybe (mapMaybe)
|
||||||
import Data.List (find)
|
import Data.List (find)
|
||||||
|
|
||||||
|
@ -27,3 +29,32 @@ concatFor = flip concatMap
|
||||||
concatFor :: [a] -> (a -> [b]) -> [b]
|
concatFor :: [a] -> (a -> [b]) -> [b]
|
||||||
concatFor = flip concatMap
|
concatFor = flip concatMap
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
infixr 3 ***, &&&
|
||||||
|
|
||||||
|
first :: (a -> a') -> (a, b) -> (a', b)
|
||||||
|
first = Arrow.first
|
||||||
|
|
||||||
|
second :: (b -> b') -> (a, b) -> (a, b')
|
||||||
|
second = Arrow.second
|
||||||
|
|
||||||
|
(***) :: (a -> a') -> (b -> b') -> (a, b) -> (a', b')
|
||||||
|
(***) = (Arrow.***)
|
||||||
|
|
||||||
|
(&&&) :: (a -> b) -> (a -> c) -> a -> (b, c)
|
||||||
|
(&&&) = (Arrow.&&&)
|
||||||
|
|
||||||
|
dupe :: a -> (a,a)
|
||||||
|
dupe x = (x, x)
|
||||||
|
|
||||||
|
both :: (a -> b) -> (a, a) -> (b, b)
|
||||||
|
both f (x, y) = (f x, f y)
|
||||||
|
|
||||||
|
fst3 :: (a, b, c) -> a
|
||||||
|
fst3 (a, _, _) = a
|
||||||
|
|
||||||
|
snd3 :: (a, b, c) -> b
|
||||||
|
snd3 (_, b, _) = b
|
||||||
|
|
||||||
|
thd3 :: (a, b, c) -> c
|
||||||
|
thd3 (_, _, c) = c
|
||||||
|
|
Loading…
Reference in New Issue