Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update custom column names on renaming/dropping columns #2933

Merged
merged 4 commits into from
Oct 3, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
9 changes: 9 additions & 0 deletions server/src-lib/Hasura/RQL/DDL/Schema/Catalog.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Hasura.RQL.DDL.Schema.Catalog
, updateTableIsEnumInCatalog
, updateTableConfig
, deleteTableFromCatalog
, getTableConfig
) where

import Hasura.Prelude
Expand Down Expand Up @@ -56,3 +57,11 @@ deleteTableFromCatalog (QualifiedObject sn tn) = liftTx $ Q.unitQE defaultTxErro
DELETE FROM "hdb_catalog"."hdb_table"
WHERE table_schema = $1 AND table_name = $2
|] (sn, tn) False

getTableConfig :: MonadTx m => QualifiedTable -> m TableConfig
getTableConfig (QualifiedObject sn tn) = liftTx $
Q.getAltJ . runIdentity . Q.getRow <$> Q.withQE defaultTxErrorHandler
[Q.sql|
SELECT configuration::json FROM hdb_catalog.hdb_table
WHERE table_schema = $1 AND table_name = $2
|] (sn, tn) True
13 changes: 13 additions & 0 deletions server/src-lib/Hasura/RQL/DDL/Schema/Rename.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import qualified Hasura.RQL.DDL.EventTrigger as DS
import Hasura.RQL.DDL.Permission
import Hasura.RQL.DDL.Permission.Internal
import Hasura.RQL.DDL.Relationship.Types
import Hasura.RQL.DDL.Schema.Catalog
import Hasura.RQL.Types
import Hasura.SQL.Types

Expand Down Expand Up @@ -97,6 +98,8 @@ renameColInCatalog oCol nCol qt ti = do
SOTableObj _ (TOTrigger triggerName) ->
updateColInEventTriggerDef triggerName $ RenameItem qt oCol nCol
d -> otherDeps errMsg d
-- Update custom column names
possiblyUpdateCustomColumnNames qt oCol nCol
where
errMsg = "cannot rename column " <> oCol <<> " to " <>> nCol
assertFldNotExists =
Expand Down Expand Up @@ -414,6 +417,16 @@ updateColMap fromQT toQT rnCol colMap =
RenameItem qt oCol nCol = rnCol
modCol colQt col = if colQt == qt && col == oCol then nCol else col

possiblyUpdateCustomColumnNames
:: MonadTx m => QualifiedTable -> PGCol -> PGCol -> m ()
possiblyUpdateCustomColumnNames qt oCol nCol = do
TableConfig customRootFields customColumns <- getTableConfig qt
let updatedCustomColumns =
M.fromList $ flip map (M.toList customColumns) $
\(dbCol, val) -> (, val) $ if dbCol == oCol then nCol else dbCol
when (updatedCustomColumns /= customColumns) $
updateTableConfig qt $ TableConfig customRootFields updatedCustomColumns

-- database functions for relationships
getRelDef :: QualifiedTable -> RelName -> Q.TxE QErr Value
getRelDef (QualifiedObject sn tn) rn =
Expand Down
40 changes: 27 additions & 13 deletions server/src-lib/Hasura/RQL/DDL/Schema/Table.hs
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,8 @@ runSetTableCustomFieldsQV2
=> SetTableCustomFields -> m EncJSON
runSetTableCustomFieldsQV2 (SetTableCustomFields tableName rootFields columnNames) = do
adminOnly
tableInfo <- askTabInfo tableName
void $ askTabInfo tableName
let tableConfig = TableConfig rootFields columnNames
validateTableConfig tableInfo tableConfig
updateTableConfig tableName tableConfig
buildSchemaCacheFor (MOTable tableName)
return successMsg
Expand Down Expand Up @@ -249,30 +248,31 @@ processTableChanges ti tableDiff = do
-- process dropped/added columns, because schema reload happens eventually
sc <- askSchemaCache
let tn = _tiName ti
withOldTabName = do
withOldTabName ccn = do
replaceConstraints tn
-- replace description
replaceDescription tn
-- for all the dropped columns
procDroppedCols tn
procAddedCols tn
procAlteredCols sc tn
procAddedCols ccn tn
procAlteredCols sc ccn tn

withNewTabName newTN = do
withNewTabName ccn newTN = do
let tnGQL = GS.qualObjectToName newTN
defGCtx = scDefaultRemoteGCtx sc
-- check for GraphQL schema conflicts on new name
GS.checkConflictingNode defGCtx tnGQL
void $ procAlteredCols sc tn
void $ procAlteredCols sc ccn tn
-- update new table in catalog
renameTableInCatalog newTN tn
return True

maybe withOldTabName withNewTabName mNewName
-- Drop custom column names for dropped columns
customColumnNames <- possiblyDropCustomColumnNames tn
maybe (withOldTabName customColumnNames) (withNewTabName customColumnNames) mNewName

where
TableDiff mNewName droppedCols addedCols alteredCols _ constraints descM = tableDiff
customFields = _tcCustomColumnNames $ _tiCustomConfig ti
replaceConstraints tn = flip modTableInCache tn $ \tInfo ->
return $ tInfo {_tiUniqOrPrimConstraints = constraints}

Expand All @@ -284,7 +284,20 @@ processTableChanges ti tableDiff = do
-- Drop the column from the cache
delColFromCache droppedCol tn

procAddedCols tn =
possiblyDropCustomColumnNames tn = do
let TableConfig customFields customColumnNames = _tiCustomConfig ti
modifiedCustomColumnNames = foldl' (flip M.delete) customColumnNames droppedCols
if modifiedCustomColumnNames == customColumnNames then
pure customColumnNames
else do
let updatedTableConfig =
TableConfig customFields modifiedCustomColumnNames
flip modTableInCache tn $ \tInfo ->
pure $ tInfo{_tiCustomConfig = updatedTableConfig}
liftTx $ updateTableConfig tn updatedTableConfig
pure modifiedCustomColumnNames

procAddedCols customColumnNames tn =
-- In the newly added columns check that there is no conflict with relationships
forM_ addedCols $ \rawInfo -> do
let colName = prciName rawInfo
Expand All @@ -294,14 +307,14 @@ processTableChanges ti tableDiff = do
<<> " in table " <> tn <<>
" as a relationship with the name already exists"
_ -> do
info <- processColumnInfoUsingCache tn customFields rawInfo
info <- processColumnInfoUsingCache tn customColumnNames rawInfo
addColToCache colName info tn

procAlteredCols sc tn = fmap or $ forM alteredCols $
procAlteredCols sc customColumnNames tn = fmap or $ forM alteredCols $
\( PGRawColumnInfo oldName oldType _ _ _
, newRawInfo@(PGRawColumnInfo newName newType _ _ _) ) -> do
let performColumnUpdate = do
newInfo <- processColumnInfoUsingCache tn customFields newRawInfo
newInfo <- processColumnInfoUsingCache tn customColumnNames newRawInfo
updColInCache newName newInfo tn

if | oldName /= newName -> renameColInCatalog oldName newName tn ti $> True
Expand Down Expand Up @@ -404,6 +417,7 @@ buildTableCache = processTableCache <=< buildRawTableCache
where
enumTables = M.mapMaybe _tiEnumValues rawTables


-- | “Processes” a 'PGRawColumnInfo' into a 'PGColumnInfo' by resolving its type using a map of known
-- enum tables.
processColumnInfo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
- description: Set custom column names
url: /v1/query
status: 200
response:
message: success
query:
type: set_table_custom_fields
version: 2
args:
table: author
custom_root_fields:
select: Authors
custom_column_names:
id: AuthorId
name: AuthorName

- description: "Rename column 'id' and drop column 'name'"
url: /v1/query
status: 200
response:
result_type: CommandOk
result: null
query:
type: run_sql
args:
sql: |
ALTER TABLE author DROP COLUMN name;
ALTER TABLE author RENAME COLUMN id to author_id;

- description: Test if custom column names are updated
url: /v1/graphql
status: 200
response:
data:
Authors:
- AuthorId: 1
age: 23
- AuthorId: 2
age: null
query:
query: |
query {
Authors{
AuthorId
age
}
}
3 changes: 3 additions & 0 deletions server/tests-py/test_v1_queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,3 +646,6 @@ def test_set_and_unset(self, hge_ctx):

def test_set_invalid_table(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + '/set_invalid_table.yaml')

def test_alter_column(self, hge_ctx):
check_query_f(hge_ctx, self.dir() + '/alter_column.yaml')