mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
server: fix one-to-one relationships
GitOrigin-RevId: e19f4dec04abbdcf4589d24031705e5c57ea1fbb
This commit is contained in:
parent
a935746e17
commit
f50f61ab6a
@ -8,6 +8,7 @@
|
||||
(Add entries below in the order of: server, console, cli, docs, others)
|
||||
|
||||
- server: fix regression: `on_conflict` was missing in the schema for inserts in tables where the current user has no columns listed in their update permissions (fix #6804)
|
||||
- server: fix one-to-one relationship bug (introduced in #459) which prevented adding one-to-one relationships which didn't have the same column name for target and source
|
||||
- console: fix Postgres table creation when table has a non-lowercase name and a comment (#6760)
|
||||
- cli: fix regression - `metadata apply —dry-run` was overwriting local metadata files with metadata on server when it should just display the differences.
|
||||
- cli: add support for `api_limits` metadata object
|
||||
|
@ -100,7 +100,7 @@ Create an ``object relationship`` ``details`` on ``author`` *table*, *using* the
|
||||
"using": {
|
||||
"foreign_key_constraint_on" : {
|
||||
"table": "author_details",
|
||||
"column": "id"
|
||||
"column": "author_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ Create an ``object relationship`` ``details`` on ``author`` *table*, *using* the
|
||||
"using": {
|
||||
"foreign_key_constraint_on" : {
|
||||
"table": "author_details",
|
||||
"column": "id"
|
||||
"column": "author_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import Hasura.RQL.DDL.Deps
|
||||
import Hasura.RQL.DDL.Permission
|
||||
import Hasura.RQL.Types
|
||||
|
||||
|
||||
runCreateRelationship
|
||||
:: forall m b a
|
||||
. (MonadError QErr m, CacheRWM m, ToJSON a, MetadataM m, Backend b, BackendMetadata b)
|
||||
@ -143,29 +144,8 @@ objRelP2Setup source qt foreignKeys (RelDef rn ru _) fieldInfoMap = case ru of
|
||||
`onNothing` throw500 "could not find column info in schema cache"
|
||||
let nullable = pgiIsNullable colInfo
|
||||
pure (RelInfo rn ObjRel colMap foreignTable False nullable BeforeParent, dependencies)
|
||||
RUFKeyOn (RemoteTable remoteTable remoteCol) -> do
|
||||
foreignTableForeignKeys <- findTable @b remoteTable foreignKeys
|
||||
ForeignKey constraint _foreignTable colMap <- getRequiredRemoteFkey remoteCol (HS.toList foreignTableForeignKeys)
|
||||
let dependencies =
|
||||
[ SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b remoteTable
|
||||
$ TOForeignKey @b (_cName constraint))
|
||||
DRRemoteFkey
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b qt
|
||||
$ TOCol @b remoteCol)
|
||||
DRUsingColumn
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITable @b remoteTable)
|
||||
DRRemoteTable
|
||||
]
|
||||
pure (RelInfo rn ObjRel colMap remoteTable False False AfterParent, dependencies)
|
||||
RUFKeyOn (RemoteTable remoteTable remoteCol) ->
|
||||
mkFkeyRel ObjRel AfterParent source rn qt remoteTable remoteCol foreignKeys
|
||||
|
||||
arrRelP2Setup
|
||||
:: forall b m
|
||||
@ -192,34 +172,50 @@ arrRelP2Setup foreignKeys source qt (RelDef rn ru _) = case ru of
|
||||
$ TOCol @b c)
|
||||
DRRightColumn)
|
||||
rCols
|
||||
pure (RelInfo rn ArrRel (rmColumns rm) refqt True True BeforeParent, deps)
|
||||
RUFKeyOn (ArrRelUsingFKeyOn refqt refCol) -> do
|
||||
foreignTableForeignKeys <- findTable @b refqt foreignKeys
|
||||
let keysThatReferenceUs = filter ((== qt) . _fkForeignTable) (HS.toList foreignTableForeignKeys)
|
||||
ForeignKey constraint _ colMap <- getRequiredFkey refCol keysThatReferenceUs
|
||||
let deps = [ SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b refqt
|
||||
$ TOForeignKey @b (_cName constraint))
|
||||
DRRemoteFkey
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b refqt
|
||||
$ TOCol @b refCol)
|
||||
DRUsingColumn
|
||||
-- we don't need to necessarily track the remote table like we did in
|
||||
-- case of obj relationships as the remote table is indirectly
|
||||
-- tracked by tracking the constraint name and 'using_col'
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITable @b refqt)
|
||||
DRRemoteTable
|
||||
]
|
||||
mapping = HM.fromList $ map swap $ HM.toList colMap
|
||||
pure (RelInfo rn ArrRel mapping refqt False False BeforeParent, deps)
|
||||
pure (RelInfo rn ArrRel (rmColumns rm) refqt True True AfterParent, deps)
|
||||
RUFKeyOn (ArrRelUsingFKeyOn refqt refCol) ->
|
||||
mkFkeyRel ArrRel AfterParent source rn qt refqt refCol foreignKeys
|
||||
|
||||
mkFkeyRel
|
||||
:: forall b m
|
||||
. QErrM m
|
||||
=> Backend b
|
||||
=> RelType
|
||||
-> InsertOrder
|
||||
-> SourceName
|
||||
-> RelName
|
||||
-> TableName b
|
||||
-> TableName b
|
||||
-> Column b
|
||||
-> HashMap (TableName b) (HashSet (ForeignKey b))
|
||||
-> m (RelInfo b, [SchemaDependency])
|
||||
mkFkeyRel relType io source rn sourceTable remoteTable remoteColumn foreignKeys = do
|
||||
foreignTableForeignKeys <- findTable @b remoteTable foreignKeys
|
||||
let keysThatReferenceUs = filter ((== sourceTable) . _fkForeignTable) (HS.toList foreignTableForeignKeys)
|
||||
ForeignKey constraint _foreignTable colMap <- getRequiredFkey remoteColumn keysThatReferenceUs
|
||||
let dependencies =
|
||||
[ SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b remoteTable
|
||||
$ TOForeignKey @b (_cName constraint))
|
||||
DRRemoteFkey
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITableObj @b remoteTable
|
||||
$ TOCol @b remoteColumn)
|
||||
DRUsingColumn
|
||||
, SchemaDependency
|
||||
(SOSourceObj source
|
||||
$ AB.mkAnyBackend
|
||||
$ SOITable @b remoteTable)
|
||||
DRRemoteTable
|
||||
]
|
||||
pure (RelInfo rn relType (reverseHM colMap) remoteTable False False io, dependencies)
|
||||
where
|
||||
reverseHM :: Eq y => Hashable y => HashMap x y -> HashMap y x
|
||||
reverseHM = HM.fromList . fmap swap . HM.toList
|
||||
|
||||
purgeRelDep
|
||||
:: forall b m
|
||||
@ -266,19 +262,3 @@ getRequiredFkey col fkeys =
|
||||
"more than one foreign key constraint exists on the given column"
|
||||
where
|
||||
filteredFkeys = filter ((== [col]) . HM.keys . _fkColumnMapping) fkeys
|
||||
|
||||
getRequiredRemoteFkey
|
||||
:: QErrM m
|
||||
=> Backend b
|
||||
=> Column b
|
||||
-> [ForeignKey b]
|
||||
-> m (ForeignKey b)
|
||||
getRequiredRemoteFkey col fkeys =
|
||||
case filteredFkeys of
|
||||
[] -> throw400 ConstraintError
|
||||
"no foreign constraint exists on the given column"
|
||||
[k] -> return k
|
||||
_ -> throw400 ConstraintError
|
||||
"more than one foreign key constraint exists on the given column"
|
||||
where
|
||||
filteredFkeys = filter ((== [col]) . HM.elems . _fkColumnMapping) fkeys
|
||||
|
@ -0,0 +1,61 @@
|
||||
#Create object relationship
|
||||
- description: Create object relationship using foreign key
|
||||
url: /v1/query
|
||||
status: 200
|
||||
response:
|
||||
message: success
|
||||
query:
|
||||
type: create_object_relationship
|
||||
args:
|
||||
table: article
|
||||
name: author
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
table: author
|
||||
column: author_id
|
||||
|
||||
- description: Nested select on article
|
||||
url: /v1/query
|
||||
status: 200
|
||||
response:
|
||||
- id: 1
|
||||
title: Article 1
|
||||
content: Sample article content 1
|
||||
author:
|
||||
id: 1
|
||||
name: Author 1
|
||||
- id: 2
|
||||
title: Article 2
|
||||
content: Sample article content 2
|
||||
author:
|
||||
id: 1
|
||||
name: Author 1
|
||||
- id: 3
|
||||
title: Article 3
|
||||
content: Sample article content 3
|
||||
author:
|
||||
id: 2
|
||||
name: Author 2
|
||||
query:
|
||||
type: select
|
||||
args:
|
||||
table: article
|
||||
columns:
|
||||
- id
|
||||
- title
|
||||
- content
|
||||
- name: author
|
||||
columns:
|
||||
- id
|
||||
- name
|
||||
|
||||
- description: Drop object relationship
|
||||
url: /v1/query
|
||||
status: 200
|
||||
response:
|
||||
message: success
|
||||
query:
|
||||
type: drop_relationship
|
||||
args:
|
||||
table: article
|
||||
relationship: author
|
Loading…
Reference in New Issue
Block a user