refactor: Rename synonyms to source columns
This commit is contained in:
committed by
Steve Chávez
parent
3b133d5554
commit
db41fb454e
@@ -49,14 +49,14 @@ getDbStructure schema pgVer = do
|
|||||||
HT.sql "set local schema ''" -- for getting the fully qualified name(schema.name) of every db object
|
HT.sql "set local schema ''" -- for getting the fully qualified name(schema.name) of every db object
|
||||||
tabs <- HT.statement () allTables
|
tabs <- HT.statement () allTables
|
||||||
cols <- HT.statement schema $ allColumns tabs
|
cols <- HT.statement schema $ allColumns tabs
|
||||||
syns <- HT.statement schema $ allSynonyms cols pgVer
|
srcCols <- HT.statement schema $ allSourceColumns cols pgVer
|
||||||
childRels <- HT.statement () $ allChildRelations tabs cols
|
childRels <- HT.statement () $ allChildRelations tabs cols
|
||||||
keys <- HT.statement () $ allPrimaryKeys tabs
|
keys <- HT.statement () $ allPrimaryKeys tabs
|
||||||
procs <- HT.statement schema allProcs
|
procs <- HT.statement schema allProcs
|
||||||
|
|
||||||
let rels = addManyToManyRelations . addParentRelations $ addViewChildRelations syns childRels
|
let rels = addManyToManyRelations . addParentRelations $ addViewChildRelations srcCols childRels
|
||||||
cols' = addForeignKeys rels cols
|
cols' = addForeignKeys rels cols
|
||||||
keys' = addViewPrimaryKeys syns keys
|
keys' = addViewPrimaryKeys srcCols keys
|
||||||
|
|
||||||
return DbStructure {
|
return DbStructure {
|
||||||
dbTables = tabs
|
dbTables = tabs
|
||||||
@@ -109,15 +109,22 @@ decodePks tables =
|
|||||||
where
|
where
|
||||||
pkRow = (,,) <$> column HD.text <*> column HD.text <*> column HD.text
|
pkRow = (,,) <$> column HD.text <*> column HD.text <*> column HD.text
|
||||||
|
|
||||||
decodeSynonyms :: [Column] -> HD.Result [Synonym]
|
decodeSourceColumns :: [Column] -> HD.Result [SourceColumn]
|
||||||
decodeSynonyms cols =
|
decodeSourceColumns cols =
|
||||||
mapMaybe (synonymFromRow cols) <$> HD.rowList synRow
|
mapMaybe (sourceColumnFromRow cols) <$> HD.rowList srcColRow
|
||||||
where
|
where
|
||||||
synRow = (,,,,,)
|
srcColRow = (,,,,,)
|
||||||
<$> column HD.text <*> column HD.text
|
<$> column HD.text <*> column HD.text
|
||||||
<*> column HD.text <*> column HD.text
|
<*> column HD.text <*> column HD.text
|
||||||
<*> column HD.text <*> column HD.text
|
<*> column HD.text <*> column HD.text
|
||||||
|
|
||||||
|
sourceColumnFromRow :: [Column] -> (Text,Text,Text,Text,Text,Text) -> Maybe SourceColumn
|
||||||
|
sourceColumnFromRow allCols (s1,t1,c1,s2,t2,c2) = (,) <$> col1 <*> col2
|
||||||
|
where
|
||||||
|
col1 = findCol s1 t1 c1
|
||||||
|
col2 = findCol s2 t2 c2
|
||||||
|
findCol s t c = find (\col -> (tableSchema . colTable) col == s && (tableName . colTable) col == t && colName col == c) allCols
|
||||||
|
|
||||||
decodeProcs :: HD.Result (M.HashMap Text [ProcDescription])
|
decodeProcs :: HD.Result (M.HashMap Text [ProcDescription])
|
||||||
decodeProcs =
|
decodeProcs =
|
||||||
-- Duplicate rows for a function means they're overloaded, order these by least args according to ProcDescription Ord instance
|
-- Duplicate rows for a function means they're overloaded, order these by least args according to ProcDescription Ord instance
|
||||||
@@ -250,13 +257,13 @@ addForeignKeys rels = map addFk
|
|||||||
return $ ForeignKey colF
|
return $ ForeignKey colF
|
||||||
|
|
||||||
{-
|
{-
|
||||||
Adds Views Child Relations based on Synonyms found, the logic is as follows:
|
Adds Views Child Relations based on SourceColumns found, the logic is as follows:
|
||||||
|
|
||||||
Having a Relation{relTable=t1, relColumns=[c1], relFTable=t2, relFColumns=[c2], relType=Child} represented by:
|
Having a Relation{relTable=t1, relColumns=[c1], relFTable=t2, relFColumns=[c2], relType=Child} represented by:
|
||||||
|
|
||||||
t1.c1------t2.c2
|
t1.c1------t2.c2
|
||||||
|
|
||||||
When only having a t1_view.c1 synonym, we need to add a View to Table Child Relation
|
When only having a t1_view.c1 source column, we need to add a View-Table Child Relation
|
||||||
|
|
||||||
t1.c1----t2.c2 t1.c1----------t2.c2
|
t1.c1----t2.c2 t1.c1----------t2.c2
|
||||||
-> ________/
|
-> ________/
|
||||||
@@ -264,58 +271,58 @@ When only having a t1_view.c1 synonym, we need to add a View to Table Child Rela
|
|||||||
t1_view.c1 t1_view.c1
|
t1_view.c1 t1_view.c1
|
||||||
|
|
||||||
|
|
||||||
When only having a t2_view.c2 synonym, we need to add a Table to View Child Relation
|
When only having a t2_view.c2 source column, we need to add a Table-View Child Relation
|
||||||
|
|
||||||
t1.c1----t2.c2 t1.c1----------t2.c2
|
t1.c1----t2.c2 t1.c1----------t2.c2
|
||||||
-> \________
|
-> \________
|
||||||
\
|
\
|
||||||
t2_view.c2 t2_view.c1
|
t2_view.c2 t2_view.c1
|
||||||
|
|
||||||
When having t1_view.c1 and a t2_view.c2 synonyms, we need to add a View to View Child Relation in addition to the prior
|
When having t1_view.c1 and a t2_view.c2 source columns, we need to add a View-View Child Relation in addition to the prior
|
||||||
|
|
||||||
t1.c1----t2.c2 t1.c1----------t2.c2
|
t1.c1----t2.c2 t1.c1----------t2.c2
|
||||||
-> \________/
|
-> \________/
|
||||||
/ \
|
/ \
|
||||||
t1_view.c1 t2_view.c2 t1_view.c1-------t2_view.c1
|
t1_view.c1 t2_view.c2 t1_view.c1-------t2_view.c1
|
||||||
|
|
||||||
The logic for composite pks is similar just need to make sure all the Relation columns have synonyms.
|
The logic for composite pks is similar just need to make sure all the Relation columns have source columns.
|
||||||
-}
|
-}
|
||||||
addViewChildRelations :: [Synonym] -> [Relation] -> [Relation]
|
addViewChildRelations :: [SourceColumn] -> [Relation] -> [Relation]
|
||||||
addViewChildRelations allSyns = concatMap (\rel ->
|
addViewChildRelations allSrcCols = concatMap (\rel ->
|
||||||
rel : case rel of
|
rel : case rel of
|
||||||
Relation{relType=Child, relTable, relColumns, relFTable, relFColumns} ->
|
Relation{relType=Child, relTable, relColumns, relFTable, relFColumns} ->
|
||||||
|
|
||||||
let colSynsGroupedByView :: [Column] -> [[Synonym]]
|
let srcColsGroupedByView :: [Column] -> [[SourceColumn]]
|
||||||
colSynsGroupedByView relCols = L.groupBy (\(_, viewCol1) (_, viewCol2) -> colTable viewCol1 == colTable viewCol2) $
|
srcColsGroupedByView relCols = L.groupBy (\(_, viewCol1) (_, viewCol2) -> colTable viewCol1 == colTable viewCol2) $
|
||||||
filter (\(c, _) -> c `elem` relCols) allSyns
|
filter (\(c, _) -> c `elem` relCols) allSrcCols
|
||||||
colsSyns = colSynsGroupedByView relColumns
|
relSrcCols = srcColsGroupedByView relColumns
|
||||||
fColsSyns = colSynsGroupedByView relFColumns
|
relFSrcCols = srcColsGroupedByView relFColumns
|
||||||
getView :: [Synonym] -> Table
|
getView :: [SourceColumn] -> Table
|
||||||
getView = colTable . snd . unsafeHead
|
getView = colTable . snd . unsafeHead
|
||||||
syns `allSynsOf` cols = S.fromList (fst <$> syns) == S.fromList cols
|
srcCols `allSrcColsOf` cols = S.fromList (fst <$> srcCols) == S.fromList cols
|
||||||
-- Relation is dependent on the order of relColumns and relFColumns to get the join conditions right in the generated query.
|
-- Relation is dependent on the order of relColumns and relFColumns to get the join conditions right in the generated query.
|
||||||
-- So we need to change the order of the synonyms to match the relColumns
|
-- So we need to change the order of the SourceColumns to match the relColumns
|
||||||
-- This could be avoided if the Relation type is improved with a structure that maintains the association of relColumns and relFColumns
|
-- TODO: This could be avoided if the Relation type is improved with a structure that maintains the association of relColumns and relFColumns
|
||||||
syns `sortAccordingTo` columns = sortOn (\(k, _) -> L.lookup k $ zip columns [0::Int ..]) syns
|
srcCols `sortAccordingTo` cols = sortOn (\(k, _) -> L.lookup k $ zip cols [0::Int ..]) srcCols
|
||||||
|
|
||||||
viewTableChild =
|
viewTableChild =
|
||||||
[ Relation (getView syns) (snd <$> syns `sortAccordingTo` relColumns)
|
[ Relation (getView srcCols) (snd <$> srcCols `sortAccordingTo` relColumns)
|
||||||
relFTable relFColumns
|
relFTable relFColumns
|
||||||
Child Nothing Nothing Nothing
|
Child Nothing Nothing Nothing
|
||||||
| syns <- colsSyns, syns `allSynsOf` relColumns ]
|
| srcCols <- relSrcCols, srcCols `allSrcColsOf` relColumns ]
|
||||||
|
|
||||||
tableViewChild =
|
tableViewChild =
|
||||||
[ Relation relTable relColumns
|
[ Relation relTable relColumns
|
||||||
(getView fSyns) (snd <$> fSyns `sortAccordingTo` relFColumns)
|
(getView fSrcCols) (snd <$> fSrcCols `sortAccordingTo` relFColumns)
|
||||||
Child Nothing Nothing Nothing
|
Child Nothing Nothing Nothing
|
||||||
| fSyns <- fColsSyns, fSyns `allSynsOf` relFColumns ]
|
| fSrcCols <- relFSrcCols, fSrcCols `allSrcColsOf` relFColumns ]
|
||||||
|
|
||||||
viewViewChild =
|
viewViewChild =
|
||||||
[ Relation (getView syns) (snd <$> syns `sortAccordingTo` relColumns)
|
[ Relation (getView srcCols) (snd <$> srcCols `sortAccordingTo` relColumns)
|
||||||
(getView fSyns) (snd <$> fSyns `sortAccordingTo` relFColumns)
|
(getView fSrcCols) (snd <$> fSrcCols `sortAccordingTo` relFColumns)
|
||||||
Child Nothing Nothing Nothing
|
Child Nothing Nothing Nothing
|
||||||
| syns <- colsSyns, syns `allSynsOf` relColumns
|
| srcCols <- relSrcCols, srcCols `allSrcColsOf` relColumns
|
||||||
, fSyns <- fColsSyns, fSyns `allSynsOf` relFColumns ]
|
, fSrcCols <- relFSrcCols, fSrcCols `allSrcColsOf` relFColumns ]
|
||||||
|
|
||||||
in viewTableChild ++ tableViewChild ++ viewViewChild
|
in viewTableChild ++ tableViewChild ++ viewViewChild
|
||||||
|
|
||||||
@@ -344,10 +351,10 @@ addManyToManyRelations rels = rels ++ addMirrorRelation (mapMaybe link2Relation
|
|||||||
| otherwise = Nothing
|
| otherwise = Nothing
|
||||||
link2Relation _ = Nothing
|
link2Relation _ = Nothing
|
||||||
|
|
||||||
addViewPrimaryKeys :: [Synonym] -> [PrimaryKey] -> [PrimaryKey]
|
addViewPrimaryKeys :: [SourceColumn] -> [PrimaryKey] -> [PrimaryKey]
|
||||||
addViewPrimaryKeys syns = concatMap (\pk ->
|
addViewPrimaryKeys srcCols = concatMap (\pk ->
|
||||||
let viewPks = (\(_, viewCol) -> PrimaryKey{pkTable=colTable viewCol, pkName=colName viewCol}) <$>
|
let viewPks = (\(_, viewCol) -> PrimaryKey{pkTable=colTable viewCol, pkName=colName viewCol}) <$>
|
||||||
filter (\(col, _) -> colTable col == pkTable pk && colName col == pkName pk) syns in
|
filter (\(col, _) -> colTable col == pkTable pk && colName col == pkName pk) srcCols in
|
||||||
pk : viewPks)
|
pk : viewPks)
|
||||||
|
|
||||||
allTables :: H.Statement () [Table]
|
allTables :: H.Statement () [Table]
|
||||||
@@ -711,9 +718,9 @@ pkFromRow :: [Table] -> (Schema, Text, Text) -> Maybe PrimaryKey
|
|||||||
pkFromRow tabs (s, t, n) = PrimaryKey <$> table <*> pure n
|
pkFromRow tabs (s, t, n) = PrimaryKey <$> table <*> pure n
|
||||||
where table = find (\tbl -> tableSchema tbl == s && tableName tbl == t) tabs
|
where table = find (\tbl -> tableSchema tbl == s && tableName tbl == t) tabs
|
||||||
|
|
||||||
allSynonyms :: [Column] -> PgVersion -> H.Statement Schema [Synonym]
|
allSourceColumns :: [Column] -> PgVersion -> H.Statement Schema [SourceColumn]
|
||||||
allSynonyms cols pgVer =
|
allSourceColumns cols pgVer =
|
||||||
H.Statement sql (param HE.text) (decodeSynonyms cols) True
|
H.Statement sql (param HE.text) (decodeSourceColumns cols) True
|
||||||
-- query explanation at https://gist.github.com/steve-chavez/7ee0e6590cddafb532e5f00c46275569
|
-- query explanation at https://gist.github.com/steve-chavez/7ee0e6590cddafb532e5f00c46275569
|
||||||
where
|
where
|
||||||
subselectRegex :: Text
|
subselectRegex :: Text
|
||||||
@@ -780,13 +787,6 @@ allSynonyms cols pgVer =
|
|||||||
where resorigtbl <> '0'
|
where resorigtbl <> '0'
|
||||||
order by view_schema, view_name, view_colum_name; |]
|
order by view_schema, view_name, view_colum_name; |]
|
||||||
|
|
||||||
synonymFromRow :: [Column] -> (Text,Text,Text,Text,Text,Text) -> Maybe Synonym
|
|
||||||
synonymFromRow allCols (s1,t1,c1,s2,t2,c2) = (,) <$> col1 <*> col2
|
|
||||||
where
|
|
||||||
col1 = findCol s1 t1 c1
|
|
||||||
col2 = findCol s2 t2 c2
|
|
||||||
findCol s t c = find (\col -> (tableSchema . colTable) col == s && (tableName . colTable) col == t && colName col == c) allCols
|
|
||||||
|
|
||||||
getPgVersion :: H.Session PgVersion
|
getPgVersion :: H.Session PgVersion
|
||||||
getPgVersion = H.statement () $ H.Statement sql HE.noParams versionRow False
|
getPgVersion = H.statement () $ H.Statement sql HE.noParams versionRow False
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -222,8 +222,8 @@ data Column =
|
|||||||
instance Eq Column where
|
instance Eq Column where
|
||||||
Column{colTable=t1,colName=n1} == Column{colTable=t2,colName=n2} = t1 == t2 && n1 == n2
|
Column{colTable=t1,colName=n1} == Column{colTable=t2,colName=n2} = t1 == t2 && n1 == n2
|
||||||
|
|
||||||
-- | A view column that refers to a table column
|
-- | The source table column a view column refers to
|
||||||
type Synonym = (Column, ViewColumn)
|
type SourceColumn = (Column, ViewColumn)
|
||||||
type ViewColumn = Column
|
type ViewColumn = Column
|
||||||
|
|
||||||
data PrimaryKey = PrimaryKey {
|
data PrimaryKey = PrimaryKey {
|
||||||
|
|||||||
Reference in New Issue
Block a user