mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-09-11 10:46:25 +03:00
Fixing issues with SQLite FKs in Schema and Suggest Relationships API Docs
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7729 GitOrigin-RevId: 4ae48019ce71f6ceb3f6d06524302bdd11ca1ed4
This commit is contained in:
parent
69ae616ae5
commit
9a54849985
@ -62,13 +62,13 @@ function nullableCast(ds: any[]): boolean {
|
||||
}
|
||||
|
||||
const formatTableInfo = (config: Config) => (info: TableInfoInternal): TableInfo => {
|
||||
const tableName = config.explicit_main_schema ? ["main", info.name] : [info.name];
|
||||
const ast = sqliteParser(info.sql);
|
||||
const columnsDdl = getColumnsDdl(ast);
|
||||
const primaryKeys = ddlPKs(ast);
|
||||
const foreignKeys = ddlFKs(config, ast);
|
||||
const foreignKeys = ddlFKs(config, tableName, ast);
|
||||
const primaryKey = primaryKeys.length > 0 ? { primary_key: primaryKeys } : {};
|
||||
const foreignKey = foreignKeys.length > 0 ? { foreign_keys: Object.fromEntries(foreignKeys) } : {};
|
||||
const tableName = config.explicit_main_schema ? ["main", info.name] : [info.name];
|
||||
|
||||
return {
|
||||
name: tableName,
|
||||
@ -146,7 +146,7 @@ function getColumnsDdl(ddl: any): any[] {
|
||||
* @param ddl
|
||||
* @returns [name, FK constraint definition][]
|
||||
*/
|
||||
function ddlFKs(config: Config, ddl: any): [string, Constraint][] {
|
||||
function ddlFKs(config: Config, tableName: Array<string>, ddl: any): [string, Constraint][] {
|
||||
if(ddl.type != 'statement' || ddl.variant != 'list') {
|
||||
throw new Error("Encountered a non-statement or non-list DDL for table.");
|
||||
}
|
||||
@ -177,7 +177,7 @@ function ddlFKs(config: Config, ddl: any): [string, Constraint][] {
|
||||
const destinationColumn = definition.references.columns[0];
|
||||
const foreignTable = config.explicit_main_schema ? ["main", definition.references.name] : [definition.references.name];
|
||||
return [[
|
||||
`${sourceColumn.name}->${definition.references.name}.${destinationColumn.name}`,
|
||||
`${tableName.join('.')}.${sourceColumn.name}->${definition.references.name}.${destinationColumn.name}`,
|
||||
{ foreign_table: foreignTable,
|
||||
column_mapping: {
|
||||
[sourceColumn.name]: destinationColumn.name
|
||||
|
@ -408,6 +408,44 @@ X-Hasura-Role: admin
|
||||
| new_name | true | [RelationshipName](/api-reference/syntax-defs.mdx#relationshipname) | New relationship name |
|
||||
| source | false | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |
|
||||
|
||||
## pg_suggest_relationships {#pg-suggest-relationships}
|
||||
|
||||
`pg_suggest_relationships` is used to suggest relationships that can be tracked by the `pg_create_*_relationship` API.
|
||||
|
||||
An example:
|
||||
|
||||
```http
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "pg_suggest_relationships",
|
||||
"version": 1,
|
||||
"args": {
|
||||
"omit_tracked": true,
|
||||
"source": "chinook",
|
||||
"tables": [["Artist"]]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Args syntax {#pg-suggest-relationship-syntax}
|
||||
|
||||
| Key | Required | Default | Schema | Description |
|
||||
| -------- | -------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| source | false | `default` | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | The source to suggest relationships for |
|
||||
| tables | false | All Tables | [ [TableName](/api-reference/syntax-defs.mdx#tablename) ] | List of tables to consider for suggestions |
|
||||
| omit_tracked | false | `false` | `Boolean` | Don't re-suggest tracked relationships |
|
||||
|
||||
|
||||
:::info Note
|
||||
|
||||
All other source kinds are also supported by using the type `{KIND}_suggest_relationships`.
|
||||
For example, Snowflake would be: `snowflake_suggest_relationships`, etc.
|
||||
|
||||
:::
|
||||
|
||||
## mssql_create_object_relationship {#mssql-create-object-relationship}
|
||||
|
||||
`create_object_relationship` is used to create an object relationship on
|
||||
@ -768,3 +806,34 @@ X-Hasura-Role: admin
|
||||
| name | true | [RelationshipName](/api-reference/syntax-defs.mdx#relationshipname) | The relationship |
|
||||
| new_name | true | [RelationshipName](/api-reference/syntax-defs.mdx#relationshipname) | New relationship name |
|
||||
| source | false | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | Name of the source database of the table (default: `default`) |
|
||||
|
||||
|
||||
## mssql_suggest_relationships {#mssql-suggest-relationships}
|
||||
|
||||
`mssql_suggest_relationships` is used to suggest relationships that can be tracked by the `mssql_create_*_relationship` API.
|
||||
|
||||
An example:
|
||||
|
||||
```http
|
||||
POST /v1/metadata HTTP/1.1
|
||||
Content-Type: application/json
|
||||
X-Hasura-Role: admin
|
||||
|
||||
{
|
||||
"type": "mssql_suggest_relationships",
|
||||
"version": 1,
|
||||
"args": {
|
||||
"omit_tracked": true,
|
||||
"source": "chinook",
|
||||
"tables": [["Artist"]]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Args syntax {#mssql-suggest-relationship-syntax}
|
||||
|
||||
| Key | Required | Default | Schema | Description |
|
||||
| -------- | -------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------- |
|
||||
| source | false | `default` | [SourceName](/api-reference/syntax-defs.mdx#sourcename) | The source to suggest relationships for |
|
||||
| tables | false | All Tables | [ [TableName](/api-reference/syntax-defs.mdx#tablename) ] | List of tables to consider for suggestions |
|
||||
| omit_tracked | false | `false` | `Boolean` | Don't re-suggest tracked relationships |
|
||||
|
@ -106,7 +106,7 @@ nameFormatting = NameFormatting id id formatForeignKeyName
|
||||
-- | Construct foreign key relationship names.
|
||||
formatForeignKeyName :: Text -> Text
|
||||
formatForeignKeyName = \case
|
||||
"Artist" -> "ArtistId->Artist.ArtistId"
|
||||
"Artist" -> "Album.ArtistId->Artist.ArtistId"
|
||||
x -> x
|
||||
|
||||
chinookFixture :: Fixture ChinookTestEnv
|
||||
|
@ -187,8 +187,7 @@ resolveDatabaseMetadata' ::
|
||||
DC.SourceConfig ->
|
||||
m (Either QErr (DBObjectsIntrospection 'DataConnector))
|
||||
resolveDatabaseMetadata' _ DC.SourceConfig {_scSchema = API.SchemaResponse {..}, ..} =
|
||||
let foreignKeys = fmap API._tiForeignKeys _srTables
|
||||
tables = Map.fromList $ do
|
||||
let tables = Map.fromList $ do
|
||||
API.TableInfo {..} <- _srTables
|
||||
let primaryKeyColumns = Seq.fromList $ coerce <$> _tiPrimaryKey
|
||||
let meta =
|
||||
@ -207,7 +206,7 @@ resolveDatabaseMetadata' _ DC.SourceConfig {_scSchema = API.SchemaResponse {..},
|
||||
},
|
||||
_ptmiPrimaryKey = RQL.T.T.PrimaryKey (RQL.T.T.Constraint (DC.ConstraintName "") (OID 0)) <$> NESeq.nonEmptySeq primaryKeyColumns,
|
||||
_ptmiUniqueConstraints = mempty,
|
||||
_ptmiForeignKeys = buildForeignKeySet foreignKeys,
|
||||
_ptmiForeignKeys = buildForeignKeySet _tiForeignKeys,
|
||||
_ptmiViewInfo =
|
||||
( if _tiType == API.Table && _tiInsertable && _tiUpdatable && _tiDeletable
|
||||
then Nothing
|
||||
@ -228,22 +227,20 @@ resolveDatabaseMetadata' _ DC.SourceConfig {_scSchema = API.SchemaResponse {..},
|
||||
-- | Construct a 'HashSet' 'RQL.T.T.ForeignKeyMetadata'
|
||||
-- 'DataConnector' to build the foreign key constraints in the table
|
||||
-- metadata.
|
||||
buildForeignKeySet :: [API.ForeignKeys] -> HashSet (RQL.T.T.ForeignKeyMetadata 'DataConnector)
|
||||
buildForeignKeySet foreignKeys =
|
||||
buildForeignKeySet :: API.ForeignKeys -> HashSet (RQL.T.T.ForeignKeyMetadata 'DataConnector)
|
||||
buildForeignKeySet (API.ForeignKeys constraints) =
|
||||
HashSet.fromList $
|
||||
join $
|
||||
foreignKeys <&> \(API.ForeignKeys constraints) ->
|
||||
constraints & HashMap.foldMapWithKey @[RQL.T.T.ForeignKeyMetadata 'DataConnector]
|
||||
\constraintName API.Constraint {..} -> maybeToList do
|
||||
let columnMapAssocList = HashMap.foldrWithKey' (\(API.ColumnName k) (API.ColumnName v) acc -> (DC.ColumnName k, DC.ColumnName v) : acc) [] _cColumnMapping
|
||||
columnMapping <- NEHashMap.fromList columnMapAssocList
|
||||
let foreignKey =
|
||||
RQL.T.T.ForeignKey
|
||||
{ _fkConstraint = RQL.T.T.Constraint (Witch.from constraintName) (OID 1),
|
||||
_fkForeignTable = Witch.from _cForeignTable,
|
||||
_fkColumnMapping = columnMapping
|
||||
}
|
||||
pure $ RQL.T.T.ForeignKeyMetadata foreignKey
|
||||
constraints & HashMap.foldMapWithKey @[RQL.T.T.ForeignKeyMetadata 'DataConnector]
|
||||
\constraintName API.Constraint {..} -> maybeToList do
|
||||
let columnMapAssocList = HashMap.foldrWithKey' (\(API.ColumnName k) (API.ColumnName v) acc -> (DC.ColumnName k, DC.ColumnName v) : acc) [] _cColumnMapping
|
||||
columnMapping <- NEHashMap.fromList columnMapAssocList
|
||||
let foreignKey =
|
||||
RQL.T.T.ForeignKey
|
||||
{ _fkConstraint = RQL.T.T.Constraint (Witch.from constraintName) (OID 1),
|
||||
_fkForeignTable = Witch.from _cForeignTable,
|
||||
_fkColumnMapping = columnMapping
|
||||
}
|
||||
pure $ RQL.T.T.ForeignKeyMetadata foreignKey
|
||||
|
||||
-- | This is needed to get permissions to work
|
||||
parseBoolExpOperations' ::
|
||||
|
Loading…
Reference in New Issue
Block a user