这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 15 additions & 20 deletions server/src-lib/Hasura/GraphQL/Schema.hs
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,9 @@ isValidField = \case
isRelEligible rn rt = isValidName (G.Name $ getRelTxt rn)
&& isValidTableName rt

upsertable :: [TableConstraint] -> Bool -> Bool -> Bool
upsertable constraints isUpsertAllowed view =
upsertable :: [ConstraintName] -> Bool -> Bool -> Bool
upsertable uniqueOrPrimaryCons isUpsertAllowed view =
not (null uniqueOrPrimaryCons) && isUpsertAllowed && not view
where
uniqueOrPrimaryCons = filter isUniqueOrPrimary constraints

toValidFieldInfos :: FieldInfoMap -> [FieldInfo]
toValidFieldInfos = filter isValidField . Map.elems
Expand All @@ -187,11 +185,9 @@ getValidCols = fst . validPartitionFieldInfoMap
getValidRels :: FieldInfoMap -> [RelInfo]
getValidRels = snd . validPartitionFieldInfoMap

mkValidConstraints :: [TableConstraint] -> [TableConstraint]
mkValidConstraints = filter isValid
where
isValid (TableConstraint _ n) =
isValidName $ G.Name $ getConstraintTxt n
mkValidConstraints :: [ConstraintName] -> [ConstraintName]
mkValidConstraints =
filter (isValidName . G.Name . getConstraintTxt)

isRelNullable :: FieldInfoMap -> RelInfo -> Bool
isRelNullable fim ri = isNullable
Expand Down Expand Up @@ -1056,11 +1052,11 @@ mkInsMutFld tn isUpsertable =
onConflictArg =
InpValInfo (Just onConflictDesc) "on_conflict" $ G.toGT $ mkOnConflictInpTy tn

mkConstriantTy :: QualifiedTable -> [TableConstraint] -> EnumTyInfo
mkConstriantTy :: QualifiedTable -> [ConstraintName] -> EnumTyInfo
mkConstriantTy tn cons = enumTyInfo
where
enumTyInfo = mkHsraEnumTyInfo (Just desc) (mkConstraintInpTy tn) $
mapFromL _eviVal $ map (mkConstraintEnumVal . tcName ) cons
mapFromL _eviVal $ map mkConstraintEnumVal cons

desc = G.Description $
"unique or primary key constraints on table " <>> tn
Expand Down Expand Up @@ -1258,16 +1254,15 @@ mkOrdByInpObj tn selFlds = (inpObjTy, ordByCtx)
-- mappend = (<>)

mkOnConflictTypes
:: QualifiedTable -> [TableConstraint] -> [PGCol] -> Bool -> [TypeInfo]
mkOnConflictTypes tn c cols =
:: QualifiedTable -> [ConstraintName] -> [PGCol] -> Bool -> [TypeInfo]
mkOnConflictTypes tn uniqueOrPrimaryCons cols =
bool [] tyInfos
where
tyInfos = [ TIEnum $ mkConflictActionTy isUpdAllowed
, TIEnum $ mkConstriantTy tn constraints
, TIEnum $ mkConstriantTy tn uniqueOrPrimaryCons
, TIEnum $ mkUpdColumnTy tn cols
, TIInpObj $ mkOnConflictInp tn
]
constraints = filter isUniqueOrPrimary c
isUpdAllowed = not $ null cols

mkGCtxRole'
Expand All @@ -1283,7 +1278,7 @@ mkGCtxRole'
-- primary key columns
-> [PGColInfo]
-- constraints
-> [TableConstraint]
-> [ConstraintName]
-> Maybe ViewInfo
-> TyAgg
mkGCtxRole' tn insPermM selPermM updColsM delPermM pkeyCols constraints viM =
Expand Down Expand Up @@ -1433,7 +1428,7 @@ mkGCtxRole' tn insPermM selPermM updColsM delPermM pkeyCols constraints viM =
getRootFldsRole'
:: QualifiedTable
-> [PGCol]
-> [TableConstraint]
-> [ConstraintName]
-> FieldInfoMap
-> Maybe ([T.Text], Bool) -- insert perm
-> Maybe (AnnBoolExpSQL, Maybe Int, [T.Text], Bool) -- select filter
Expand Down Expand Up @@ -1576,7 +1571,7 @@ mkGCtxRole
-> QualifiedTable
-> FieldInfoMap
-> [PGCol]
-> [TableConstraint]
-> [ConstraintName]
-> Maybe ViewInfo
-> RoleName
-> RolePermInfo
Expand All @@ -1601,7 +1596,7 @@ mkGCtxRole tableCache tn fields pCols constraints viM role permInfo = do
getRootFldsRole
:: QualifiedTable
-> [PGCol]
-> [TableConstraint]
-> [ConstraintName]
-> FieldInfoMap
-> Maybe ViewInfo
-> RolePermInfo
Expand Down Expand Up @@ -1671,7 +1666,7 @@ checkSchemaConflicts gCtx remoteCtx = do
(\k _ -> G.unNamedType k `notElem` builtinTy ++ rmRootNames)
$ _gTypes remoteCtx

isTyInfoSame ty = any (\t -> tyinfoEq t ty) hTypes
isTyInfoSame ty = any (`tyinfoEq` ty) hTypes
-- name is same and structure is not same
isSame n ty = G.unNamedType n `elem` hTyNames &&
not (isTyInfoSame ty)
Expand Down
49 changes: 33 additions & 16 deletions server/src-lib/Hasura/RQL/DDL/Schema/Diff.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ $(deriveJSON (aesonDrop 3 snakeCase){omitNothingFields=True} ''PGColMeta)

data ConstraintMeta
= ConstraintMeta
{ cmConstraintName :: !ConstraintName
, cmConstraintOid :: !Int
{ cmName :: !ConstraintName
, cmOid :: !Int
, cmType :: !ConstraintType
} deriving (Show, Eq)

$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''ConstraintMeta)
Expand Down Expand Up @@ -84,11 +85,19 @@ fetchTableMeta = do
ON (t.table_schema = c.table_schema AND t.table_name = c.table_name)
LEFT OUTER JOIN
(SELECT
table_schema,
table_name,
json_agg((SELECT r FROM (SELECT constraint_name, constraint_oid) r)) as constraints
tc.table_schema,
tc.table_name,
json_agg(
json_build_object(
'name', tc.constraint_name,
'oid', r.oid::integer,
'type', tc.constraint_type
)
) as constraints
FROM
hdb_catalog.hdb_foreign_key_constraint
information_schema.table_constraints tc
JOIN pg_catalog.pg_constraint r
ON tc.constraint_name = r.conname
GROUP BY
table_schema, table_name) f
ON (t.table_schema = f.table_schema AND t.table_name = f.table_name)
Expand All @@ -114,21 +123,29 @@ getDifference getKey left right =

data TableDiff
= TableDiff
{ _tdNewName :: !(Maybe QualifiedTable)
, _tdDroppedCols :: ![PGCol]
, _tdAddedCols :: ![PGColInfo]
, _tdAlteredCols :: ![(PGColInfo, PGColInfo)]
, _tdDroppedCons :: ![ConstraintName]
{ _tdNewName :: !(Maybe QualifiedTable)
, _tdDroppedCols :: ![PGCol]
, _tdAddedCols :: ![PGColInfo]
, _tdAlteredCols :: ![(PGColInfo, PGColInfo)]
, _tdDroppedFKeyCons :: ![ConstraintName]
-- The final list of uniq/primary constraint names
-- used for generating types on_conflict clauses
-- TODO: this ideally should't be part of TableDiff
, _tdUniqOrPriCons :: ![ConstraintName]
} deriving (Show, Eq)

getTableDiff :: TableMeta -> TableMeta -> TableDiff
getTableDiff oldtm newtm =
TableDiff mNewName droppedCols addedCols alteredCols droppedConstraints
TableDiff mNewName droppedCols addedCols alteredCols
droppedFKeyConstraints uniqueOrPrimaryCons
where
mNewName = bool (Just $ tmTable newtm) Nothing $ tmTable oldtm == tmTable newtm
oldCols = tmColumns oldtm
newCols = tmColumns newtm

uniqueOrPrimaryCons =
[cmName cm | cm <- tmConstraints newtm, isUniqueOrPrimary $ cmType cm]

droppedCols =
map pcmColumnName $ getDifference pcmOrdinalPosition oldCols newCols

Expand All @@ -144,8 +161,8 @@ getTableDiff oldtm newtm =
flip map (filter (uncurry (/=)) existingCols) $ \(pcmo, pcmn) ->
(pcmToPci pcmo, pcmToPci pcmn)

droppedConstraints =
map cmConstraintName $ getDifference cmConstraintOid
droppedFKeyConstraints = map cmName $
filter (isForeignKey . cmType) $ getDifference cmOid
(tmConstraints oldtm) (tmConstraints newtm)

getTableChangeDeps
Expand All @@ -158,13 +175,13 @@ getTableChangeDeps ti tableDiff = do
let objId = SOTableObj tn $ TOCol droppedCol
return $ getDependentObjs sc objId
-- for all dropped constraints
droppedConsDeps <- fmap concat $ forM droppedConstraints $ \droppedCons -> do
droppedConsDeps <- fmap concat $ forM droppedFKeyConstraints $ \droppedCons -> do
let objId = SOTableObj tn $ TOCons droppedCons
return $ getDependentObjs sc objId
return $ droppedConsDeps <> droppedColDeps
where
tn = tiName ti
TableDiff _ droppedCols _ _ droppedConstraints = tableDiff
TableDiff _ droppedCols _ _ droppedFKeyConstraints _ = tableDiff

data SchemaDiff
= SchemaDiff
Expand Down
7 changes: 6 additions & 1 deletion server/src-lib/Hasura/RQL/DDL/Schema/Table.hs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ processTableChanges ti tableDiff = do
when (isJust mNewName) $
throw400 NotSupported $ "table renames are not yet supported : " <>> tn

-- replace constraints
replaceConstraints

-- for all the dropped columns
forM_ droppedCols $ \droppedCol ->
-- Drop the column from the cache
Expand Down Expand Up @@ -168,8 +171,10 @@ processTableChanges ti tableDiff = do
updateFldInCache cn ci = do
delColFromCache cn tn
addColToCache cn ci tn
replaceConstraints = flip modTableInCache tn $ \tInfo ->
return $ tInfo {tiUniqOrPrimConstraints = constraints}
tn = tiName ti
TableDiff mNewName droppedCols addedCols alteredCols _ = tableDiff
TableDiff mNewName droppedCols addedCols alteredCols _ constraints = tableDiff

delTableAndDirectDeps
:: (QErrM m, CacheRWM m, MonadTx m) => QualifiedTable -> m ()
Expand Down
2 changes: 1 addition & 1 deletion server/src-lib/Hasura/RQL/DML/Insert.hs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ buildConflictClause tableInfo inpCols (OnConflict mTCol mTCons act) =
\pgCol -> askPGType fieldInfoMap pgCol ""

validateConstraint c = do
let tableConsNames = map tcName $ tiConstraints tableInfo
let tableConsNames = tiUniqOrPrimConstraints tableInfo
withPathK "constraint" $
unless (c `elem` tableConsNames) $
throw400 Unexpected $ "constraint " <> getConstraintTxt c
Expand Down
46 changes: 26 additions & 20 deletions server/src-lib/Hasura/RQL/Types/SchemaCache.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module Hasura.RQL.Types.SchemaCache
, onlyJSONBCols
, onlyComparableCols
, isUniqueOrPrimary
, isForeignKey
, mkTableInfo
, addTableToCache
, modTableInCache
Expand Down Expand Up @@ -259,8 +260,6 @@ data ConstraintType
| CTUNIQUE
deriving Eq

$(deriveToJSON defaultOptions{constructorTagModifier = drop 2} ''ConstraintType)

constraintTyToTxt :: ConstraintType -> T.Text
constraintTyToTxt ty = case ty of
CTCHECK -> "CHECK"
Expand All @@ -279,6 +278,20 @@ instance FromJSON ConstraintType where
"UNIQUE" -> return CTUNIQUE
c -> fail $ "unexpected ConstraintType: " <> T.unpack c

instance ToJSON ConstraintType where
toJSON = String . constraintTyToTxt

isUniqueOrPrimary :: ConstraintType -> Bool
isUniqueOrPrimary = \case
CTPRIMARYKEY -> True
CTUNIQUE -> True
_ -> False

isForeignKey :: ConstraintType -> Bool
isForeignKey = \case
CTFOREIGNKEY -> True
_ -> False

data TableConstraint
= TableConstraint
{ tcType :: !ConstraintType
Expand All @@ -287,13 +300,6 @@ data TableConstraint

$(deriveJSON (aesonDrop 2 snakeCase) ''TableConstraint)

isUniqueOrPrimary :: TableConstraint -> Bool
isUniqueOrPrimary (TableConstraint ty _) = case ty of
CTCHECK -> False
CTFOREIGNKEY -> False
CTPRIMARYKEY -> True
CTUNIQUE -> True

data ViewInfo
= ViewInfo
{ viIsUpdatable :: !Bool
Expand All @@ -316,28 +322,28 @@ mutableView qt f mVI operation =

data TableInfo
= TableInfo
{ tiName :: !QualifiedTable
, tiSystemDefined :: !Bool
, tiFieldInfoMap :: !FieldInfoMap
, tiRolePermInfoMap :: !RolePermInfoMap
, tiConstraints :: ![TableConstraint]
, tiPrimaryKeyCols :: ![PGCol]
, tiViewInfo :: !(Maybe ViewInfo)
, tiEventTriggerInfoMap :: !EventTriggerInfoMap
{ tiName :: !QualifiedTable
, tiSystemDefined :: !Bool
, tiFieldInfoMap :: !FieldInfoMap
, tiRolePermInfoMap :: !RolePermInfoMap
, tiUniqOrPrimConstraints :: ![ConstraintName]
, tiPrimaryKeyCols :: ![PGCol]
, tiViewInfo :: !(Maybe ViewInfo)
, tiEventTriggerInfoMap :: !EventTriggerInfoMap
} deriving (Show, Eq)

$(deriveToJSON (aesonDrop 2 snakeCase) ''TableInfo)

mkTableInfo
:: QualifiedTable
-> Bool
-> [TableConstraint]
-> [ConstraintName]
-> [PGColInfo]
-> [PGCol]
-> Maybe ViewInfo -> TableInfo
mkTableInfo tn isSystemDefined constraints cols pcols mVI =
mkTableInfo tn isSystemDefined uniqCons cols pcols mVI =
TableInfo tn isSystemDefined colMap (M.fromList [])
constraints pcols mVI (M.fromList [])
uniqCons pcols mVI (M.fromList [])
where
colMap = M.fromList $ map f cols
f colInfo = (fromPGCol $ pgiName colInfo, FIColumn colInfo)
Expand Down
12 changes: 4 additions & 8 deletions server/src-rsr/table_info.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,12 @@ from
select
c.table_schema,
c.table_name,
json_agg(
json_build_object(
'name',
constraint_name,
'type',
constraint_type
)
) as constraints
json_agg(constraint_name) as constraints
from
information_schema.table_constraints c
where
c.constraint_type = 'UNIQUE'
or c.constraint_type = 'PRIMARY KEY'
group by
c.table_schema,
c.table_name
Expand Down