Support joins on nested fields for MongoDB

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/10345
GitOrigin-RevId: 1a4886b7ac5110ddf9233596068810963bde3371
This commit is contained in:
David Overton 2023-10-30 13:25:57 +11:00 committed by hasura-bot
parent 04e21a34af
commit 82fa13db6e
70 changed files with 908 additions and 314 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@hasura/dc-api-types", "name": "@hasura/dc-api-types",
"version": "0.42.0", "version": "0.43.0",
"description": "Hasura GraphQL Engine Data Connector Agent API types", "description": "Hasura GraphQL Engine Data Connector Agent API types",
"author": "Hasura (https://github.com/hasura/graphql-engine)", "author": "Hasura (https://github.com/hasura/graphql-engine)",
"license": "Apache-2.0", "license": "Apache-2.0",

View File

@ -1334,11 +1334,42 @@
"Constraint": { "Constraint": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"description": "The columns on which you want want to define the foreign key.", "additionalProperties": {
"type": "object" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
},
{
"additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
}
],
"description": "The columns on which you want want to define the foreign key."
}, },
"foreign_table": { "foreign_table": {
"$ref": "#/components/schemas/TableName" "$ref": "#/components/schemas/TableName"
@ -1845,11 +1876,42 @@
"Relationship": { "Relationship": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"description": "A mapping between columns on the source table to columns on the target table", "additionalProperties": {
"type": "object" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
},
{
"additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
}
],
"description": "A mapping between columns on the source table to columns on the target table"
}, },
"relationship_type": { "relationship_type": {
"$ref": "#/components/schemas/RelationshipType" "$ref": "#/components/schemas/RelationshipType"
@ -2068,19 +2130,18 @@
"$ref": "#/components/schemas/ScalarType" "$ref": "#/components/schemas/ScalarType"
}, },
"name": { "name": {
"additionalProperties": true, "description": "The name of the column",
"anyOf": [ "oneOf": [
{
"type": "string"
},
{ {
"items": { "items": {
"type": "string" "type": "string"
}, },
"type": "array" "type": "array"
},
{
"type": "string"
} }
], ]
"description": "The name of the column"
}, },
"path": { "path": {
"default": [], "default": [],
@ -2620,16 +2681,15 @@
"OrderByColumn": { "OrderByColumn": {
"properties": { "properties": {
"column": { "column": {
"additionalProperties": true, "oneOf": [
"anyOf": [
{
"type": "string"
},
{ {
"items": { "items": {
"type": "string" "type": "string"
}, },
"type": "array" "type": "array"
},
{
"type": "string"
} }
] ]
}, },

View File

@ -10,7 +10,7 @@ export type ComparisonColumn = {
/** /**
* The name of the column * The name of the column
*/ */
name: (string | Array<string>); name: (Array<string> | string);
/** /**
* The path to the table that contains the specified column. Missing or empty array means the current table. ["$"] means the query table. No other values are supported at this time. * The path to the table that contains the specified column. Missing or empty array means the current table. ["$"] means the query table. No other values are supported at this time.
*/ */

View File

@ -8,7 +8,7 @@ export type Constraint = {
/** /**
* The columns on which you want want to define the foreign key. * The columns on which you want want to define the foreign key.
*/ */
column_mapping: Record<string, string>; column_mapping: Record<string, (Array<string> | string)>;
foreign_table: TableName; foreign_table: TableName;
}; };

View File

@ -5,7 +5,7 @@
import type { RedactionExpressionName } from './RedactionExpressionName'; import type { RedactionExpressionName } from './RedactionExpressionName';
export type OrderByColumn = { export type OrderByColumn = {
column: (string | Array<string>); column: (Array<string> | string);
redaction_expression?: RedactionExpressionName; redaction_expression?: RedactionExpressionName;
type: 'column'; type: 'column';
}; };

View File

@ -9,7 +9,7 @@ export type Relationship = {
/** /**
* A mapping between columns on the source table to columns on the target table * A mapping between columns on the source table to columns on the target table
*/ */
column_mapping: Record<string, string>; column_mapping: Record<string, (Array<string> | string)>;
relationship_type: RelationshipType; relationship_type: RelationshipType;
target: Target; target: Target;
}; };

View File

@ -24,7 +24,7 @@
}, },
"dc-api-types": { "dc-api-types": {
"name": "@hasura/dc-api-types", "name": "@hasura/dc-api-types",
"version": "0.42.0", "version": "0.43.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@tsconfig/node16": "^1.0.3", "@tsconfig/node16": "^1.0.3",
@ -2227,7 +2227,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"mathjs": "^11.0.0", "mathjs": "^11.0.0",
"pino-pretty": "^8.0.0", "pino-pretty": "^8.0.0",
@ -2547,7 +2547,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"fastify-metrics": "^9.2.1", "fastify-metrics": "^9.2.1",
"nanoid": "^3.3.4", "nanoid": "^3.3.4",
@ -2868,7 +2868,7 @@
"version": "file:reference", "version": "file:reference",
"requires": { "requires": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"@tsconfig/node16": "^1.0.3", "@tsconfig/node16": "^1.0.3",
"@types/node": "^16.11.49", "@types/node": "^16.11.49",
"@types/xml2js": "^0.4.11", "@types/xml2js": "^0.4.11",
@ -3080,7 +3080,7 @@
"version": "file:sqlite", "version": "file:sqlite",
"requires": { "requires": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"@tsconfig/node16": "^1.0.3", "@tsconfig/node16": "^1.0.3",
"@types/node": "^16.11.49", "@types/node": "^16.11.49",
"@types/sqlite3": "^3.1.8", "@types/sqlite3": "^3.1.8",

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"mathjs": "^11.0.0", "mathjs": "^11.0.0",
"pino-pretty": "^8.0.0", "pino-pretty": "^8.0.0",
@ -52,7 +52,7 @@
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
}, },
"node_modules/@hasura/dc-api-types": { "node_modules/@hasura/dc-api-types": {
"version": "0.42.0", "version": "0.43.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@tsconfig/node16": "^1.0.3", "@tsconfig/node16": "^1.0.3",

View File

@ -22,7 +22,7 @@
}, },
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"mathjs": "^11.0.0", "mathjs": "^11.0.0",
"pino-pretty": "^8.0.0", "pino-pretty": "^8.0.0",

View File

@ -175,7 +175,7 @@ export const getSchema = (store: Record<string, StaticData>, config: Config, req
? mapObjectValues(table.foreign_keys, constraint => ({ ? mapObjectValues(table.foreign_keys, constraint => ({
...constraint, ...constraint,
foreign_table: prefixSchemaToTableName(constraint.foreign_table.map(applyTableNameCasing)), foreign_table: prefixSchemaToTableName(constraint.foreign_table.map(applyTableNameCasing)),
column_mapping: mapObject(constraint.column_mapping, ([outer, inner]) => [applyColumnNameCasing(outer), applyColumnNameCasing(inner)]) column_mapping: mapObject(constraint.column_mapping as Record<string, string>, ([outer, inner]) => [applyColumnNameCasing(outer), applyColumnNameCasing(inner)])
})) }))
: table.foreign_keys, : table.foreign_keys,
columns: table.columns?.map(column => ({ columns: table.columns?.map(column => ({

View File

@ -484,7 +484,7 @@ const makeApplyRedaction = (
const createFilterExpressionForRelationshipJoin = (row: Record<string, RawScalarValue>, relationship: Relationship): Expression | null => { const createFilterExpressionForRelationshipJoin = (row: Record<string, RawScalarValue>, relationship: Relationship): Expression | null => {
const columnMappings = Object.entries(relationship.column_mapping); const columnMappings = Object.entries(relationship.column_mapping);
const filterConditions: Expression[] = columnMappings const filterConditions: Expression[] = columnMappings
.map(([outerColumnName, innerColumnName]): [RawScalarValue, string] => [row[outerColumnName], innerColumnName]) .map(([outerColumnName, innerColumnName]): [RawScalarValue, string] => [row[outerColumnName], innerColumnName as string])
.filter((x): x is [RawScalarValue, string] => { .filter((x): x is [RawScalarValue, string] => {
const [outerValue, _] = x; const [outerValue, _] = x;
return outerValue !== null; return outerValue !== null;

View File

@ -10,7 +10,7 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"fastify-metrics": "^9.2.1", "fastify-metrics": "^9.2.1",
"nanoid": "^3.3.4", "nanoid": "^3.3.4",
@ -57,7 +57,7 @@
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
}, },
"node_modules/@hasura/dc-api-types": { "node_modules/@hasura/dc-api-types": {
"version": "0.42.0", "version": "0.43.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"devDependencies": { "devDependencies": {
"@tsconfig/node16": "^1.0.3", "@tsconfig/node16": "^1.0.3",

View File

@ -22,7 +22,7 @@
}, },
"dependencies": { "dependencies": {
"@fastify/cors": "^8.1.0", "@fastify/cors": "^8.1.0",
"@hasura/dc-api-types": "0.42.0", "@hasura/dc-api-types": "0.43.0",
"fastify-metrics": "^9.2.1", "fastify-metrics": "^9.2.1",
"fastify": "^4.13.0", "fastify": "^4.13.0",
"nanoid": "^3.3.4", "nanoid": "^3.3.4",

View File

@ -234,7 +234,7 @@ function generateRelationshipJoinComparisonFragments(relationship: Relationship,
return Object return Object
.entries(relationship.column_mapping) .entries(relationship.column_mapping)
.map(([sourceColumnName, targetColumnName]) => .map(([sourceColumnName, targetColumnName]) =>
`${sourceTablePrefix}${escapeIdentifier(sourceColumnName)} = ${targetTableAlias}.${escapeIdentifier(targetColumnName)}`); `${sourceTablePrefix}${escapeIdentifier(sourceColumnName)} = ${targetTableAlias}.${escapeIdentifier(targetColumnName as string)}`);
} }
function generateComparisonColumnFragment(comparisonColumn: ComparisonColumn, queryTableAlias: string, currentTableAlias: string): string { function generateComparisonColumnFragment(comparisonColumn: ComparisonColumn, queryTableAlias: string, currentTableAlias: string): string {
@ -419,7 +419,7 @@ function target_query( // TODO: Rename as `target_query`
function relationship(ts: Relationships[], r: Relationship, field: RelationshipField, sourceTableAlias: string): string { function relationship(ts: Relationships[], r: Relationship, field: RelationshipField, sourceTableAlias: string): string {
const relationshipJoinInfo = { const relationshipJoinInfo = {
sourceTableAlias, sourceTableAlias,
columnMapping: r.column_mapping, columnMapping: r.column_mapping as Record<string, string>,
}; };
// We force a limit of 1 for object relationships in case the user has configured a manual // We force a limit of 1 for object relationships in case the user has configured a manual
@ -638,7 +638,7 @@ function generateOrderByAggregateTargetJoinInfo(
default: unreachable(element.target["type"]); default: unreachable(element.target["type"]);
} }
}); });
const joinColumns = Object.values(relationship.column_mapping).map(escapeIdentifier); const joinColumns = Object.values(relationship.column_mapping as Record<string, string>).map(escapeIdentifier);
const selectColumns = [...joinColumns, aggregateColumnsFragments]; const selectColumns = [...joinColumns, aggregateColumnsFragments];
const whereClause = whereExpression ? `WHERE ${where_clause(allTableRelationships, whereExpression, relationship.target, subqueryTableAlias)}` : ""; const whereClause = whereExpression ? `WHERE ${where_clause(allTableRelationships, whereExpression, relationship.target, subqueryTableAlias)}` : "";
const aggregateSubquery = `SELECT ${selectColumns.join(", ")} FROM ${escapeTargetName(relationship.target)} AS ${subqueryTableAlias} ${whereClause} GROUP BY ${joinColumns.join(", ")}` const aggregateSubquery = `SELECT ${selectColumns.join(", ")} FROM ${escapeTargetName(relationship.target)} AS ${subqueryTableAlias} ${whereClause} GROUP BY ${joinColumns.join(", ")}`

View File

@ -965,10 +965,21 @@
"BigqueryRelManualNativeQueryConfig": { "BigqueryRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -991,10 +1002,21 @@
"BigqueryRelManualTableConfig": { "BigqueryRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -1946,10 +1968,21 @@
"CitusRelManualNativeQueryConfig": { "CitusRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -1972,10 +2005,21 @@
"CitusRelManualTableConfig": { "CitusRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -2954,10 +2998,21 @@
"CockroachRelManualNativeQueryConfig": { "CockroachRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -2980,10 +3035,21 @@
"CockroachRelManualTableConfig": { "CockroachRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -3733,7 +3799,17 @@
"properties": { "properties": {
"columns": { "columns": {
"items": { "items": {
"type": "string" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
}, },
"type": "array" "type": "array"
}, },
@ -3753,7 +3829,17 @@
"DataconnectorArrRelUsingFKeyOnSingleColumn": { "DataconnectorArrRelUsingFKeyOnSingleColumn": {
"properties": { "properties": {
"column": { "column": {
"type": "string" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
}, },
"table": { "table": {
"items": { "items": {
@ -4055,7 +4141,17 @@
"properties": { "properties": {
"columns": { "columns": {
"items": { "items": {
"type": "string" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
}, },
"type": "array" "type": "array"
}, },
@ -4075,7 +4171,17 @@
"DataconnectorObjRelRemoteTableSingleColumn": { "DataconnectorObjRelRemoteTableSingleColumn": {
"properties": { "properties": {
"column": { "column": {
"type": "string" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
}, },
"table": { "table": {
"items": { "items": {
@ -4112,10 +4218,41 @@
"DataconnectorRelManualNativeQueryConfig": { "DataconnectorRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
},
{
"additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -4138,10 +4275,41 @@
"DataconnectorRelManualTableConfig": { "DataconnectorRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
},
{
"additionalProperties": {
"oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -5825,10 +5993,21 @@
"MssqlRelManualNativeQueryConfig": { "MssqlRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -5851,10 +6030,21 @@
"MssqlRelManualTableConfig": { "MssqlRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -7208,10 +7398,21 @@
"PostgresRelManualNativeQueryConfig": { "PostgresRelManualNativeQueryConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -7234,10 +7435,21 @@
"PostgresRelManualTableConfig": { "PostgresRelManualTableConfig": {
"properties": { "properties": {
"column_mapping": { "column_mapping": {
"additionalProperties": { "additionalProperties": true,
"type": "string" "anyOf": [
}, {
"type": "object" "additionalProperties": {
"type": "string"
},
"type": "object"
},
{
"additionalProperties": {
"type": "string"
},
"type": "object"
}
]
}, },
"insertion_order": { "insertion_order": {
"enum": [ "enum": [
@ -7933,12 +8145,28 @@
"properties": { "properties": {
"foreign_key_constraint_on": { "foreign_key_constraint_on": {
"oneOf": [ "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{ {
"type": "string" "type": "string"
}, },
{ {
"items": { "items": {
"type": "string" "oneOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"type": "string"
}
]
}, },
"type": "array" "type": "array"
}, },

View File

@ -177,7 +177,7 @@ tests = describe "Aggregate Query Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Album", { _rTarget = mkTableTarget "Album",
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]
@ -300,7 +300,7 @@ tests = describe "Aggregate Query Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "InvoiceLine", { _rTarget = mkTableTarget "InvoiceLine",
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "InvoiceId", API.ColumnName "InvoiceId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "InvoiceId", API.mkColumnSelector $ API.ColumnName "InvoiceId")]
} }
) )
] ]

View File

@ -18,7 +18,7 @@ import Harness.Test.BackendType qualified as BackendType
import Harness.Test.Fixture qualified as Fixture import Harness.Test.Fixture qualified as Fixture
import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment) import Harness.TestEnvironment (GlobalTestEnvironment, TestEnvironment)
import Harness.Yaml (shouldBeYaml) import Harness.Yaml (shouldBeYaml)
import Hasura.Backends.DataConnector.API (ColumnName (..), ScalarType (..), ScalarValue (..)) import Hasura.Backends.DataConnector.API (ColumnName (..), ScalarType (..), ScalarValue (..), mkColumnSelector)
import Hasura.Backends.DataConnector.API qualified as API import Hasura.Backends.DataConnector.API qualified as API
import Hasura.Backends.DataConnector.API.V0.Expression import Hasura.Backends.DataConnector.API.V0.Expression
import Hasura.Prelude import Hasura.Prelude

View File

@ -189,7 +189,7 @@ tests = do
API.Relationship API.Relationship
{ API._rTarget = mkTableTarget "Artist", { API._rTarget = mkTableTarget "Artist",
API._rRelationshipType = API.ObjectRelationship, API._rRelationshipType = API.ObjectRelationship,
API._rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] API._rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]
@ -298,7 +298,7 @@ tests = do
API.Relationship API.Relationship
{ API._rTarget = mkTableTarget "Artist", { API._rTarget = mkTableTarget "Artist",
API._rRelationshipType = API.ObjectRelationship, API._rRelationshipType = API.ObjectRelationship,
API._rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] API._rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]

View File

@ -181,7 +181,7 @@ tests = do
API.Relationship API.Relationship
{ API._rTarget = mkTableTarget "Artist", { API._rTarget = mkTableTarget "Artist",
API._rRelationshipType = API.ObjectRelationship, API._rRelationshipType = API.ObjectRelationship,
API._rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] API._rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]

View File

@ -200,7 +200,7 @@ tests = describe "Order By Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Album", { _rTarget = mkTableTarget "Album",
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]

View File

@ -228,7 +228,7 @@ tests = describe "Object Relationships Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Genre", { _rTarget = mkTableTarget "Genre",
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "GenreId", API.ColumnName "GenreId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "GenreId", API.mkColumnSelector $ API.ColumnName "GenreId")]
} }
), ),
( API.RelationshipName "MediaType", ( API.RelationshipName "MediaType",
@ -236,8 +236,9 @@ tests = describe "Object Relationships Tests" $ do
{ _rTarget = mkTableTarget "MediaType", { _rTarget = mkTableTarget "MediaType",
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = _rColumnMapping =
HashMap.fromList API.ColumnPathMapping
[(API.ColumnName "MediaTypeId", API.ColumnName "MediaTypeId")] $ HashMap.fromList
[(API.mkColumnSelector $ API.ColumnName "MediaTypeId", API.mkColumnSelector $ API.ColumnName "MediaTypeId")]
} }
) )
] ]
@ -354,7 +355,9 @@ tests = describe "Object Relationships Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Album", { _rTarget = mkTableTarget "Album",
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "AlbumId", API.ColumnName "AlbumId")] _rColumnMapping =
API.ColumnPathMapping
$ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "AlbumId", API.mkColumnSelector $ API.ColumnName "AlbumId")]
} }
) )
] ]
@ -368,7 +371,9 @@ tests = describe "Object Relationships Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Artist", { _rTarget = mkTableTarget "Artist",
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] _rColumnMapping =
API.ColumnPathMapping
$ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
} }
) )
] ]
@ -449,7 +454,7 @@ tests = describe "Object Relationships Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Employee", { _rTarget = mkTableTarget "Employee",
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "SupportRepId", API.ColumnName "EmployeeId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "SupportRepId", API.mkColumnSelector $ API.ColumnName "EmployeeId")]
} }
) )
] ]
@ -463,7 +468,7 @@ tests = describe "Object Relationships Tests" $ do
API.Relationship API.Relationship
{ _rTarget = mkTableTarget "Customer", { _rTarget = mkTableTarget "Customer",
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList [(API.ColumnName "EmployeeId", API.ColumnName "SupportRepId")] _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "EmployeeId", API.mkColumnSelector $ API.ColumnName "SupportRepId")]
} }
) )
] ]

View File

@ -203,7 +203,7 @@ tests = do
API.Relationship API.Relationship
{ API._rTarget = mkTableTarget "Genre", { API._rTarget = mkTableTarget "Genre",
API._rRelationshipType = API.ObjectRelationship, API._rRelationshipType = API.ObjectRelationship,
API._rColumnMapping = HashMap.fromList [(API.ColumnName "GenreId", API.ColumnName "GenreId")] API._rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "GenreId", API.mkColumnSelector $ API.ColumnName "GenreId")]
} }
) )
] ]
@ -394,7 +394,7 @@ tests = do
API.Relationship API.Relationship
{ API._rTarget = mkTableTarget "Genre", { API._rTarget = mkTableTarget "Genre",
API._rRelationshipType = API.ObjectRelationship, API._rRelationshipType = API.ObjectRelationship,
API._rColumnMapping = HashMap.fromList [(API.ColumnName "GenreId", API.ColumnName "GenreId")] API._rColumnMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "GenreId", API.mkColumnSelector $ API.ColumnName "GenreId")]
} }
) )
] ]

View File

@ -3,6 +3,8 @@
module Hasura.Backends.DataConnector.API.V0.Column module Hasura.Backends.DataConnector.API.V0.Column
( ColumnName (..), ( ColumnName (..),
ColumnSelector (..),
mkColumnSelector,
ColumnType (..), ColumnType (..),
ColumnInfo (..), ColumnInfo (..),
ciName, ciName,
@ -13,19 +15,24 @@ module Hasura.Backends.DataConnector.API.V0.Column
ciUpdatable, ciUpdatable,
ciValueGenerated, ciValueGenerated,
ColumnValueGenerationStrategy (..), ColumnValueGenerationStrategy (..),
ColumnPathMapping (..),
) )
where where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Autodocodec import Autodocodec.Extended
import Autodocodec.OpenAPI () import Autodocodec.OpenAPI ()
import Control.DeepSeq (NFData) import Control.DeepSeq (NFData)
import Control.Lens.TH (makeLenses) import Control.Lens.TH (makeLenses)
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey) import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Bitraversable (bitraverse)
import Data.Data (Data) import Data.Data (Data)
import Data.Either.Extra (maybeToEither)
import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.List.NonEmpty (NonEmpty (..))
import Data.OpenApi (ToSchema) import Data.OpenApi (ToSchema)
import Data.Text (Text) import Data.Text (Text)
import GHC.Generics (Generic) import GHC.Generics (Generic)
@ -46,6 +53,31 @@ instance HasCodec ColumnName where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
data ColumnSelector
= ColumnSelectorPath (NonEmpty ColumnName)
| ColumnSelectorColumn (ColumnName)
deriving stock (Eq, Ord, Show, Generic)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec ColumnSelector
deriving anyclass (Hashable, NFData)
instance HasCodec ColumnSelector where
codec = disjointMatchChoiceCodec pathCodec columnCodec chooser
where
pathCodec = dimapCodec ColumnSelectorPath id (codec @(NonEmpty ColumnName))
columnCodec = dimapCodec ColumnSelectorColumn id (codec @ColumnName)
chooser = \case
ColumnSelectorPath p -> Left p
ColumnSelectorColumn c -> Right c
instance FromJSONKey ColumnSelector
instance ToJSONKey ColumnSelector
mkColumnSelector :: ColumnName -> ColumnSelector
mkColumnSelector = ColumnSelectorColumn
--------------------------------------------------------------------------------
data ColumnType data ColumnType
= ColumnTypeScalar API.V0.Scalar.ScalarType = ColumnTypeScalar API.V0.Scalar.ScalarType
| ColumnTypeObject G.Name | ColumnTypeObject G.Name
@ -135,3 +167,33 @@ instance HasCodec ColumnValueGenerationStrategy where
] ]
$(makeLenses ''ColumnInfo) $(makeLenses ''ColumnInfo)
newtype ColumnPathMapping = ColumnPathMapping {unColumnPathMapping :: HashMap ColumnSelector ColumnSelector}
deriving stock (Eq, Ord, Show, Generic)
deriving newtype (NFData, Hashable)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec ColumnPathMapping
-- If all keys in the ColumnPathMapping are ColumnSelectors with a single column then we
-- want to represent the mapping as a JSON object with the source columns as properties
-- (using `codec @(HashMap ColumnName ColumnSelector)).
-- This is required for backwards compatibility of the DC API.
-- If some of the keys are not singletons then we can't use a JSON object so we use
-- an array of pairs instead, as provided by `codec @(HashMap ColumnSelector ColumnSelector)`.
instance HasCodec ColumnPathMapping where
codec =
matchChoiceCodec
(dimapCodec ColumnPathMapping unColumnPathMapping $ codec @(HashMap ColumnSelector ColumnSelector))
(dimapCodec columnMappingToColumnPathMapping id $ codec @(HashMap ColumnName ColumnSelector))
\m -> maybeToEither m (tryColumnPathMappingToColumnMapping m)
where
columnMappingToColumnPathMapping :: HashMap ColumnName ColumnSelector -> ColumnPathMapping
columnMappingToColumnPathMapping = ColumnPathMapping . HashMap.mapKeys mkColumnSelector
tryColumnPathMappingToColumnMapping :: ColumnPathMapping -> Maybe (HashMap ColumnName ColumnSelector)
tryColumnPathMappingToColumnMapping =
fmap HashMap.fromList . traverse (bitraverse tryColumnSelectorToColumnName pure) . HashMap.toList . unColumnPathMapping
tryColumnSelectorToColumnName :: ColumnSelector -> Maybe ColumnName
tryColumnSelectorToColumnName = \case
ColumnSelectorColumn columnName -> Just columnName
_ -> Nothing

View File

@ -14,8 +14,6 @@ module Hasura.Backends.DataConnector.API.V0.Expression
ccColumnType, ccColumnType,
ccRedactionExpression, ccRedactionExpression,
ColumnPath (..), ColumnPath (..),
ColumnSelector (..),
mkColumnSelector,
ComparisonValue (..), ComparisonValue (..),
TargetRedactionExpressions (..), TargetRedactionExpressions (..),
RedactionExpressionName (..), RedactionExpressionName (..),
@ -32,8 +30,6 @@ import Data.Data (Data)
import Data.HashMap.Strict (HashMap) import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NonEmpty
import Data.OpenApi (ToSchema) import Data.OpenApi (ToSchema)
import Data.Set (Set) import Data.Set (Set)
import Data.Text (Text) import Data.Text (Text)
@ -258,7 +254,7 @@ data ComparisonColumn = ComparisonColumn
{ -- | The path to the table that contains the specified column. { -- | The path to the table that contains the specified column.
_ccPath :: ColumnPath, _ccPath :: ColumnPath,
-- | The name of the column -- | The name of the column
_ccName :: ColumnSelector, _ccName :: API.V0.ColumnSelector,
-- | The scalar type of the column -- | The scalar type of the column
_ccColumnType :: API.V0.ScalarType, _ccColumnType :: API.V0.ScalarType,
-- | If present, the name of the redaction expression to evaluate. -- | If present, the name of the redaction expression to evaluate.
@ -309,20 +305,6 @@ instance HasCodec ColumnPath where
CurrentTable -> [] CurrentTable -> []
QueryTable -> ["$"] QueryTable -> ["$"]
newtype ColumnSelector = ColumnSelector {unColumnSelector :: NonEmpty API.V0.ColumnName}
deriving stock (Eq, Ord, Show, Generic)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec ColumnSelector
deriving anyclass (Hashable, NFData)
instance HasCodec ColumnSelector where
codec = bimapCodec dec enc oneOrManyCodec
where
dec = maybe (Left "Unexpected empty list in ColumnSelector") (Right . ColumnSelector) . NonEmpty.nonEmpty
enc = NonEmpty.toList . unColumnSelector
mkColumnSelector :: API.V0.ColumnName -> ColumnSelector
mkColumnSelector = ColumnSelector . NonEmpty.singleton
-- | A serializable representation of comparison values used in comparisons inside 'Expression's. -- | A serializable representation of comparison values used in comparisons inside 'Expression's.
data ComparisonValue data ComparisonValue
= -- | Allows a comparison to a column on the current table or another table = -- | Allows a comparison to a column on the current table or another table

View File

@ -30,6 +30,7 @@ import Data.List.NonEmpty (NonEmpty)
import Data.OpenApi (ToSchema) import Data.OpenApi (ToSchema)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Hasura.Backends.DataConnector.API.V0.Aggregate qualified as API.V0 import Hasura.Backends.DataConnector.API.V0.Aggregate qualified as API.V0
import Hasura.Backends.DataConnector.API.V0.Column qualified as API.V0
import Hasura.Backends.DataConnector.API.V0.Expression qualified as API.V0 import Hasura.Backends.DataConnector.API.V0.Expression qualified as API.V0
import Hasura.Backends.DataConnector.API.V0.Relationships qualified as API.V0 import Hasura.Backends.DataConnector.API.V0.Relationships qualified as API.V0
import Prelude import Prelude

View File

@ -33,6 +33,7 @@ module Hasura.Backends.DataConnector.API.V0.Query
qrAggregates, qrAggregates,
qrInterpolatedQueries, qrInterpolatedQueries,
FieldValue, FieldValue,
unFieldValue,
mkColumnFieldValue, mkColumnFieldValue,
mkRelationshipFieldValue, mkRelationshipFieldValue,
mkNestedObjFieldValue, mkNestedObjFieldValue,
@ -299,7 +300,7 @@ instance HasStatus QueryResponse where
-- field values (mainly for testing purposes), we must compare them using 'QueryResponse', -- field values (mainly for testing purposes), we must compare them using 'QueryResponse',
-- since raw JSON comparisons will show up immaterial differences between null properties -- since raw JSON comparisons will show up immaterial differences between null properties
-- and missing properties (which we consider to be the same thing here). -- and missing properties (which we consider to be the same thing here).
newtype FieldValue = FieldValue J.Value newtype FieldValue = FieldValue {unFieldValue :: J.Value}
deriving (ToJSON, FromJSON, ToSchema) via Autodocodec FieldValue deriving (ToJSON, FromJSON, ToSchema) via Autodocodec FieldValue
instance Eq FieldValue where instance Eq FieldValue where

View File

@ -30,6 +30,7 @@ import Control.DeepSeq (NFData)
import Control.Lens (makeLenses, makePrisms) import Control.Lens (makeLenses, makePrisms)
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey) import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import Data.Data (Data) import Data.Data (Data)
import Data.HashMap.Strict (HashMap)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Data.OpenApi (ToSchema) import Data.OpenApi (ToSchema)
@ -43,13 +44,13 @@ import Hasura.Backends.DataConnector.API.V0.Target qualified as API.V0
import Prelude import Prelude
data Relationships = RTable TableRelationships | RFunction FunctionRelationships | RInterpolated InterpolatedRelationships data Relationships = RTable TableRelationships | RFunction FunctionRelationships | RInterpolated InterpolatedRelationships
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec Relationships deriving (FromJSON, ToJSON, ToSchema) via Autodocodec Relationships
pattern RTableRelationships :: API.V0.TableName -> HashMap.HashMap RelationshipName Relationship -> Relationships pattern RTableRelationships :: API.V0.TableName -> HashMap RelationshipName Relationship -> Relationships
pattern RTableRelationships source rels = RTable (TableRelationships source rels) pattern RTableRelationships source rels = RTable (TableRelationships source rels)
pattern RFunctionRelationships :: API.V0.FunctionName -> HashMap.HashMap RelationshipName Relationship -> Relationships pattern RFunctionRelationships :: API.V0.FunctionName -> HashMap RelationshipName Relationship -> Relationships
pattern RFunctionRelationships source rels = RFunction (FunctionRelationships source rels) pattern RFunctionRelationships source rels = RFunction (FunctionRelationships source rels)
instance HasCodec Relationships where instance HasCodec Relationships where
@ -71,9 +72,9 @@ instance HasCodec Relationships where
data InterpolatedRelationships = InterpolatedRelationships data InterpolatedRelationships = InterpolatedRelationships
{ _irSource :: API.V0.InterpolatedQueryId, { _irSource :: API.V0.InterpolatedQueryId,
_irRelationships :: HashMap.HashMap RelationshipName Relationship _irRelationships :: HashMap RelationshipName Relationship
} }
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
instance HasObjectCodec InterpolatedRelationships where instance HasObjectCodec InterpolatedRelationships where
objectCodec = objectCodec =
@ -84,9 +85,9 @@ instance HasObjectCodec InterpolatedRelationships where
-- NOTE: Prefix is `trel` due to TableRequest conflicting with `tr` prefix. -- NOTE: Prefix is `trel` due to TableRequest conflicting with `tr` prefix.
data TableRelationships = TableRelationships data TableRelationships = TableRelationships
{ _trelSourceTable :: API.V0.TableName, { _trelSourceTable :: API.V0.TableName,
_trelRelationships :: HashMap.HashMap RelationshipName Relationship _trelRelationships :: HashMap RelationshipName Relationship
} }
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
instance HasObjectCodec TableRelationships where instance HasObjectCodec TableRelationships where
objectCodec = objectCodec =
@ -96,9 +97,9 @@ instance HasObjectCodec TableRelationships where
data FunctionRelationships = FunctionRelationships data FunctionRelationships = FunctionRelationships
{ _frelSourceFunction :: API.V0.FunctionName, { _frelSourceFunction :: API.V0.FunctionName,
_frelRelationships :: HashMap.HashMap RelationshipName Relationship _frelRelationships :: HashMap RelationshipName Relationship
} }
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
instance HasObjectCodec FunctionRelationships where instance HasObjectCodec FunctionRelationships where
objectCodec = objectCodec =
@ -110,9 +111,9 @@ instance HasObjectCodec FunctionRelationships where
data Relationship = Relationship data Relationship = Relationship
{ _rTarget :: API.V0.Target, { _rTarget :: API.V0.Target,
_rRelationshipType :: RelationshipType, _rRelationshipType :: RelationshipType,
_rColumnMapping :: HashMap.HashMap SourceColumnName TargetColumnName _rColumnMapping :: API.V0.ColumnPathMapping
} }
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
deriving (FromJSON, ToJSON, ToSchema) via Autodocodec Relationship deriving (FromJSON, ToJSON, ToSchema) via Autodocodec Relationship
instance HasCodec Relationship where instance HasCodec Relationship where
@ -140,9 +141,9 @@ instance HasCodec RelationshipType where
named "RelationshipType" $ named "RelationshipType" $
stringConstCodec [(ObjectRelationship, "object"), (ArrayRelationship, "array")] stringConstCodec [(ObjectRelationship, "object"), (ArrayRelationship, "array")]
type SourceColumnName = API.V0.ColumnName type SourceColumnName = API.V0.ColumnSelector
type TargetColumnName = API.V0.ColumnName type TargetColumnName = API.V0.ColumnSelector
$(makeLenses 'TableRelationships) $(makeLenses 'TableRelationships)
$(makeLenses 'Relationship) $(makeLenses 'Relationship)

View File

@ -122,7 +122,7 @@ instance HasCodec TableType where
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
newtype ForeignKeys = ForeignKeys {_unForeignKeys :: HashMap ConstraintName Constraint} newtype ForeignKeys = ForeignKeys {_unForeignKeys :: HashMap ConstraintName Constraint}
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
deriving anyclass (NFData, Hashable) deriving anyclass (NFData, Hashable)
deriving (FromJSON, ToJSON) via Autodocodec ForeignKeys deriving (FromJSON, ToJSON) via Autodocodec ForeignKeys
@ -138,9 +138,9 @@ newtype ConstraintName = ConstraintName {unConstraintName :: Text}
data Constraint = Constraint data Constraint = Constraint
{ _cForeignTable :: TableName, { _cForeignTable :: TableName,
_cColumnMapping :: HashMap API.V0.ColumnName API.V0.ColumnName _cColumnMapping :: API.V0.ColumnPathMapping
} }
deriving stock (Eq, Ord, Show, Generic, Data) deriving stock (Eq, Ord, Show, Generic)
deriving anyclass (NFData, Hashable) deriving anyclass (NFData, Hashable)
deriving (FromJSON, ToJSON) via Autodocodec Constraint deriving (FromJSON, ToJSON) via Autodocodec Constraint

View File

@ -155,7 +155,7 @@ albumsRelationshipName = API.RelationshipName "Albums"
artistsTableRelationships :: API.TableRelationships artistsTableRelationships :: API.TableRelationships
artistsTableRelationships = artistsTableRelationships =
let joinFieldMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] let joinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
in API.TableRelationships in API.TableRelationships
artistsTableName artistsTableName
( HashMap.fromList ( HashMap.fromList
@ -175,8 +175,8 @@ albumsRowsById =
albumsTableRelationships :: API.TableRelationships albumsTableRelationships :: API.TableRelationships
albumsTableRelationships = albumsTableRelationships =
let artistsJoinFieldMapping = HashMap.fromList [(API.ColumnName "ArtistId", API.ColumnName "ArtistId")] let artistsJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ArtistId", API.mkColumnSelector $ API.ColumnName "ArtistId")]
tracksJoinFieldMapping = HashMap.fromList [(API.ColumnName "AlbumId", API.ColumnName "AlbumId")] tracksJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "AlbumId", API.mkColumnSelector $ API.ColumnName "AlbumId")]
in API.TableRelationships in API.TableRelationships
albumsTableName albumsTableName
( HashMap.fromList ( HashMap.fromList
@ -203,8 +203,8 @@ customersRowsById =
customersTableRelationships :: API.TableRelationships customersTableRelationships :: API.TableRelationships
customersTableRelationships = customersTableRelationships =
let supportRepJoinFieldMapping = HashMap.fromList [(API.ColumnName "SupportRepId", API.ColumnName "EmployeeId")] let supportRepJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "SupportRepId", API.mkColumnSelector $ API.ColumnName "EmployeeId")]
invoicesJoinFieldMapping = HashMap.fromList [(API.ColumnName "CustomerId", API.ColumnName "CustomerId")] invoicesJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "CustomerId", API.mkColumnSelector $ API.ColumnName "CustomerId")]
in API.TableRelationships in API.TableRelationships
customersTableName customersTableName
( HashMap.fromList ( HashMap.fromList
@ -231,8 +231,8 @@ employeesRowsById =
employeesTableRelationships :: API.TableRelationships employeesTableRelationships :: API.TableRelationships
employeesTableRelationships = employeesTableRelationships =
let supportRepJoinFieldMapping = HashMap.fromList [(API.ColumnName "EmployeeId", API.ColumnName "SupportRepId")] let supportRepJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "EmployeeId", API.mkColumnSelector $ API.ColumnName "SupportRepId")]
reportsToEmployeeJoinFieldMapping = HashMap.fromList [(API.ColumnName "ReportsTo", API.ColumnName "EmployeeId")] reportsToEmployeeJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "ReportsTo", API.mkColumnSelector $ API.ColumnName "EmployeeId")]
in API.TableRelationships in API.TableRelationships
employeesTableName employeesTableName
( HashMap.fromList ( HashMap.fromList
@ -259,8 +259,8 @@ invoicesRowsById =
invoicesTableRelationships :: API.TableRelationships invoicesTableRelationships :: API.TableRelationships
invoicesTableRelationships = invoicesTableRelationships =
let invoiceLinesJoinFieldMapping = HashMap.fromList [(API.ColumnName "InvoiceId", API.ColumnName "InvoiceId")] let invoiceLinesJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "InvoiceId", API.mkColumnSelector $ API.ColumnName "InvoiceId")]
customersJoinFieldMapping = HashMap.fromList [(API.ColumnName "CustomerId", API.ColumnName "CustomerId")] customersJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "CustomerId", API.mkColumnSelector $ API.ColumnName "CustomerId")]
in API.TableRelationships in API.TableRelationships
invoicesTableName invoicesTableName
( HashMap.fromList ( HashMap.fromList
@ -280,8 +280,8 @@ invoiceLinesRows = sortBy (API.FieldName "InvoiceLineId") $ readTableFromXmlInto
invoiceLinesTableRelationships :: API.TableRelationships invoiceLinesTableRelationships :: API.TableRelationships
invoiceLinesTableRelationships = invoiceLinesTableRelationships =
let invoiceJoinFieldMapping = HashMap.fromList [(API.ColumnName "InvoiceId", API.ColumnName "InvoiceId")] let invoiceJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "InvoiceId", API.mkColumnSelector $ API.ColumnName "InvoiceId")]
tracksJoinFieldMapping = HashMap.fromList [(API.ColumnName "TrackId", API.ColumnName "TrackId")] tracksJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "TrackId", API.mkColumnSelector $ API.ColumnName "TrackId")]
in API.TableRelationships in API.TableRelationships
invoiceLinesTableName invoiceLinesTableName
( HashMap.fromList ( HashMap.fromList
@ -314,11 +314,11 @@ tracksRowsById =
tracksTableRelationships :: API.TableRelationships tracksTableRelationships :: API.TableRelationships
tracksTableRelationships = tracksTableRelationships =
let invoiceLinesJoinFieldMapping = HashMap.fromList [(API.ColumnName "TrackId", API.ColumnName "TrackId")] let invoiceLinesJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "TrackId", API.mkColumnSelector $ API.ColumnName "TrackId")]
mediaTypeJoinFieldMapping = HashMap.fromList [(API.ColumnName "MediaTypeId", API.ColumnName "MediaTypeId")] mediaTypeJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "MediaTypeId", API.mkColumnSelector $ API.ColumnName "MediaTypeId")]
albumJoinFieldMapping = HashMap.fromList [(API.ColumnName "AlbumId", API.ColumnName "AlbumId")] albumJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "AlbumId", API.mkColumnSelector $ API.ColumnName "AlbumId")]
genreJoinFieldMapping = HashMap.fromList [(API.ColumnName "GenreId", API.ColumnName "GenreId")] genreJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "GenreId", API.mkColumnSelector $ API.ColumnName "GenreId")]
playlistTracksJoinFieldMapping = HashMap.fromList [(API.ColumnName "TrackId", API.ColumnName "TrackId")] playlistTracksJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "TrackId", API.mkColumnSelector $ API.ColumnName "TrackId")]
in API.TableRelationships in API.TableRelationships
tracksTableName tracksTableName
( HashMap.fromList ( HashMap.fromList
@ -359,7 +359,7 @@ mkFibonacciRows n = take n $ fibonacciRow <$> fibs
genresTableRelationships :: API.TableRelationships genresTableRelationships :: API.TableRelationships
genresTableRelationships = genresTableRelationships =
let joinFieldMapping = HashMap.fromList [(API.ColumnName "GenreId", API.ColumnName "GenreId")] let joinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "GenreId", API.mkColumnSelector $ API.ColumnName "GenreId")]
in API.TableRelationships in API.TableRelationships
genresTableName genresTableName
( HashMap.fromList ( HashMap.fromList
@ -538,7 +538,13 @@ mkTestData schemaResponse testConfig =
formatTableRelationships :: API.TableRelationships -> API.TableRelationships formatTableRelationships :: API.TableRelationships -> API.TableRelationships
formatTableRelationships = formatTableRelationships =
prefixTableRelationships prefixTableRelationships
>>> API.trelRelationships . traverse . API.rColumnMapping %~ (HashMap.toList >>> fmap (bimap (formatColumnName testConfig) (formatColumnName testConfig)) >>> HashMap.fromList) >>> API.trelRelationships . traverse . API.rColumnMapping
%~ ( API.unColumnPathMapping
>>> HashMap.toList
>>> fmap (bimap (formatColumnSelector testConfig) (formatColumnSelector testConfig))
>>> HashMap.fromList
>>> API.ColumnPathMapping
)
prefixTableRelationships :: API.TableRelationships -> API.TableRelationships prefixTableRelationships :: API.TableRelationships -> API.TableRelationships
prefixTableRelationships = prefixTableRelationships =
@ -623,7 +629,7 @@ formatTableInfo testConfig =
>>> API.tiPrimaryKey . _Just . traverse %~ formatColumnName testConfig >>> API.tiPrimaryKey . _Just . traverse %~ formatColumnName testConfig
>>> API.tiForeignKeys . API.unForeignKeys . traverse >>> API.tiForeignKeys . API.unForeignKeys . traverse
%~ ( API.cForeignTable %~ formatTableName testConfig %~ ( API.cForeignTable %~ formatTableName testConfig
>>> API.cColumnMapping %~ (HashMap.toList >>> fmap (bimap (formatColumnName testConfig) (formatColumnName testConfig)) >>> HashMap.fromList) >>> API.cColumnMapping %~ (API.unColumnPathMapping >>> HashMap.toList >>> fmap (bimap (formatColumnSelector testConfig) (formatColumnSelector testConfig)) >>> HashMap.fromList >>> API.ColumnPathMapping)
) )
applyTableNamePrefix :: [Text] -> API.TableName -> API.TableName applyTableNamePrefix :: [Text] -> API.TableName -> API.TableName
@ -647,6 +653,11 @@ applyNameCasing casing text = case casing of
formatColumnName :: TestConfig -> API.ColumnName -> API.ColumnName formatColumnName :: TestConfig -> API.ColumnName -> API.ColumnName
formatColumnName TestConfig {..} = API.ColumnName . applyNameCasing _tcColumnNameCasing . API.unColumnName formatColumnName TestConfig {..} = API.ColumnName . applyNameCasing _tcColumnNameCasing . API.unColumnName
formatColumnSelector :: TestConfig -> API.ColumnSelector -> API.ColumnSelector
formatColumnSelector testConfig = \case
API.ColumnSelectorPath p -> API.ColumnSelectorPath $ formatColumnName testConfig <$> p
API.ColumnSelectorColumn c -> API.ColumnSelectorColumn $ formatColumnName testConfig c
columnField :: API.SchemaResponse -> TestConfig -> API.TableName -> Text -> API.Field columnField :: API.SchemaResponse -> TestConfig -> API.TableName -> Text -> API.Field
columnField schemaResponse testConfig tableName columnName = columnField schemaResponse testConfig tableName columnName =
API.ColumnField columnName' scalarType Nothing API.ColumnField columnName' scalarType Nothing

View File

@ -116,7 +116,7 @@ spec testConfig API.Capabilities {} = describe "supports functions" $ preloadAge
] ]
query' = Data.emptyQuery & qFields ?~ fields query' = Data.emptyQuery & qFields ?~ fields
authorRelationship = authorRelationship =
let authorsJoinFieldMapping = HashMap.fromList [(API.ColumnName "author_id", API.ColumnName "id")] let authorsJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "author_id", API.mkColumnSelector $ API.ColumnName "id")]
in API.FunctionRelationships in API.FunctionRelationships
_ftdSearchArticlesFunctionName _ftdSearchArticlesFunctionName
( HashMap.fromList ( HashMap.fromList
@ -164,7 +164,7 @@ spec testConfig API.Capabilities {} = describe "supports functions" $ preloadAge
(API.ScalarValueComparison (API.ScalarValue (Number 10) (API.ScalarType "number"))) (API.ScalarValueComparison (API.ScalarValue (Number 10) (API.ScalarType "number")))
query' = Data.emptyQuery & qFields ?~ fields & qWhere ?~ whereClause & qLimit ?~ 2 query' = Data.emptyQuery & qFields ?~ fields & qWhere ?~ whereClause & qLimit ?~ 2
authorRelationship = authorRelationship =
let authorsJoinFieldMapping = HashMap.fromList [(API.ColumnName "author_id", API.ColumnName "id")] let authorsJoinFieldMapping = API.ColumnPathMapping $ HashMap.fromList [(API.mkColumnSelector $ API.ColumnName "author_id", API.mkColumnSelector $ API.ColumnName "id")]
in API.FunctionRelationships in API.FunctionRelationships
_ftdSearchArticlesFunctionName _ftdSearchArticlesFunctionName
( HashMap.fromList ( HashMap.fromList

View File

@ -220,7 +220,12 @@ schema =
API._tiDescription = Just "Collection of music albums created by artists", API._tiDescription = Just "Collection of music albums created by artists",
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.singleton (API.ConstraintName "Artist") (API.Constraint (mkTableName "Artist") (HashMap.singleton (API.ColumnName "ArtistId") (API.ColumnName "ArtistId"))), $ HashMap.singleton
(API.ConstraintName "Artist")
( API.Constraint
(mkTableName "Artist")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "ArtistId") (API.mkColumnSelector $ API.ColumnName "ArtistId"))
),
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,
API._tiDeletable = True API._tiDeletable = True
@ -351,7 +356,12 @@ schema =
API._tiDescription = Just "Collection of customers who can buy tracks", API._tiDescription = Just "Collection of customers who can buy tracks",
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.singleton (API.ConstraintName "CustomerSupportRep") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "SupportRepId") (API.ColumnName "EmployeeId"))), $ HashMap.singleton
(API.ConstraintName "CustomerSupportRep")
( API.Constraint
(mkTableName "Employee")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "SupportRepId") (API.mkColumnSelector $ API.ColumnName "EmployeeId"))
),
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,
API._tiDeletable = True API._tiDeletable = True
@ -500,7 +510,12 @@ schema =
API._tiDescription = Just "Collection of employees who work for the business", API._tiDescription = Just "Collection of employees who work for the business",
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.singleton (API.ConstraintName "EmployeeReportsTo") (API.Constraint (mkTableName "Employee") (HashMap.singleton (API.ColumnName "ReportsTo") (API.ColumnName "EmployeeId"))), $ HashMap.singleton
(API.ConstraintName "EmployeeReportsTo")
( API.Constraint
(mkTableName "Employee")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "ReportsTo") (API.mkColumnSelector $ API.ColumnName "EmployeeId"))
),
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,
API._tiDeletable = True API._tiDeletable = True
@ -626,7 +641,9 @@ schema =
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.singleton (API.ConstraintName "InvoiceCustomer") $ HashMap.singleton (API.ConstraintName "InvoiceCustomer")
$ API.Constraint (mkTableName "Customer") (HashMap.singleton (API.ColumnName "CustomerId") (API.ColumnName "CustomerId")), $ API.Constraint
(mkTableName "Customer")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "CustomerId") (API.mkColumnSelector $ API.ColumnName "CustomerId")),
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,
API._tiDeletable = True API._tiDeletable = True
@ -686,8 +703,16 @@ schema =
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.fromList $ HashMap.fromList
[ (API.ConstraintName "Invoice", API.Constraint (mkTableName "Invoice") (HashMap.singleton (API.ColumnName "InvoiceId") (API.ColumnName "InvoiceId"))), [ ( API.ConstraintName "Invoice",
(API.ConstraintName "Track", API.Constraint (mkTableName "Track") (HashMap.singleton (API.ColumnName "TrackId") (API.ColumnName "TrackId"))) API.Constraint
(mkTableName "Invoice")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "InvoiceId") (API.mkColumnSelector $ API.ColumnName "InvoiceId"))
),
( API.ConstraintName "Track",
API.Constraint
(mkTableName "Track")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "TrackId") (API.mkColumnSelector $ API.ColumnName "TrackId"))
)
], ],
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,
@ -814,9 +839,21 @@ schema =
API._tiForeignKeys = API._tiForeignKeys =
API.ForeignKeys API.ForeignKeys
$ HashMap.fromList $ HashMap.fromList
[ (API.ConstraintName "Album", API.Constraint (mkTableName "Album") (HashMap.singleton (API.ColumnName "AlbumId") (API.ColumnName "AlbumId"))), [ ( API.ConstraintName "Album",
(API.ConstraintName "Genre", API.Constraint (mkTableName "Genre") (HashMap.singleton (API.ColumnName "GenreId") (API.ColumnName "GenreId"))), API.Constraint
(API.ConstraintName "MediaType", API.Constraint (mkTableName "MediaType") (HashMap.singleton (API.ColumnName "MediaTypeId") (API.ColumnName "MediaTypeId"))) (mkTableName "Album")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "AlbumId") (API.mkColumnSelector $ API.ColumnName "AlbumId"))
),
( API.ConstraintName "Genre",
API.Constraint
(mkTableName "Genre")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "GenreId") (API.mkColumnSelector $ API.ColumnName "GenreId"))
),
( API.ConstraintName "MediaType",
API.Constraint
(mkTableName "MediaType")
(API.ColumnPathMapping $ HashMap.singleton (API.mkColumnSelector $ API.ColumnName "MediaTypeId") (API.mkColumnSelector $ API.ColumnName "MediaTypeId"))
)
], ],
API._tiInsertable = True, API._tiInsertable = True,
API._tiUpdatable = True, API._tiUpdatable = True,

View File

@ -632,7 +632,7 @@ unfurlAnnotatedOrderByElement =
pure (fieldName, expression) pure (fieldName, expression)
Ir.AOCObjectRelation Rql.RelInfo {riTarget = Rql.RelTargetNativeQuery _} _annBoolExp _annOrderByElementG -> Ir.AOCObjectRelation Rql.RelInfo {riTarget = Rql.RelTargetNativeQuery _} _annBoolExp _annOrderByElementG ->
error "unfurlAnnotatedOrderByElement RelTargetNativeQuery" error "unfurlAnnotatedOrderByElement RelTargetNativeQuery"
Ir.AOCObjectRelation Rql.RelInfo {riMapping = mapping, riTarget = Rql.RelTargetTable tableName} annBoolExp annOrderByElementG -> do Ir.AOCObjectRelation Rql.RelInfo {riMapping = Rql.RelMapping mapping, riTarget = Rql.RelTargetTable tableName} annBoolExp annOrderByElementG -> do
selectFrom <- lift (lift (fromQualifiedTable tableName)) selectFrom <- lift (lift (fromQualifiedTable tableName))
joinAliasEntity <- joinAliasEntity <-
lift (lift (generateEntityAlias (ForOrderAlias (tableNameText tableName)))) lift (lift (generateEntityAlias (ForOrderAlias (tableNameText tableName))))
@ -674,7 +674,7 @@ unfurlAnnotatedOrderByElement =
local (const joinAliasEntity) (unfurlAnnotatedOrderByElement annOrderByElementG) local (const joinAliasEntity) (unfurlAnnotatedOrderByElement annOrderByElementG)
Ir.AOCArrayAggregation Rql.RelInfo {riTarget = Rql.RelTargetNativeQuery _} _annBoolExp _annAggregateOrderBy -> Ir.AOCArrayAggregation Rql.RelInfo {riTarget = Rql.RelTargetNativeQuery _} _annBoolExp _annAggregateOrderBy ->
error "unfurlAnnotatedOrderByElement RelTargetNativeQuery" error "unfurlAnnotatedOrderByElement RelTargetNativeQuery"
Ir.AOCArrayAggregation Rql.RelInfo {riMapping = mapping, riTarget = Rql.RelTargetTable tableName} annBoolExp annAggregateOrderBy -> do Ir.AOCArrayAggregation Rql.RelInfo {riMapping = Rql.RelMapping mapping, riTarget = Rql.RelTargetTable tableName} annBoolExp annAggregateOrderBy -> do
selectFrom <- lift (lift (fromQualifiedTable tableName)) selectFrom <- lift (lift (fromQualifiedTable tableName))
let alias = aggFieldName let alias = aggFieldName
joinAlias <- joinAlias <-
@ -835,7 +835,7 @@ fromAnnBoolExpFld =
error "fromAnnBoolExpFld RelTargetNativeQuery" error "fromAnnBoolExpFld RelTargetNativeQuery"
Ir.AVRemoteRelationship _ -> Ir.AVRemoteRelationship _ ->
error "fromAnnBoolExpFld RemoteRelationship" error "fromAnnBoolExpFld RemoteRelationship"
Ir.AVRelationship Rql.RelInfo {riMapping = mapping, riTarget = Rql.RelTargetTable table} (Ir.RelationshipFilters tablePerms annBoolExp) -> do Ir.AVRelationship Rql.RelInfo {riMapping = Rql.RelMapping mapping, riTarget = Rql.RelTargetTable table} (Ir.RelationshipFilters tablePerms annBoolExp) -> do
selectFrom <- lift (fromQualifiedTable table) selectFrom <- lift (fromQualifiedTable table)
foreignKeyConditions <- fromMapping selectFrom mapping foreignKeyConditions <- fromMapping selectFrom mapping
whereExpression <- whereExpression <-

View File

@ -28,6 +28,7 @@ instance Backend 'BigQuery where
type NullsOrderType 'BigQuery = BigQuery.NullsOrder type NullsOrderType 'BigQuery = BigQuery.NullsOrder
type CountType 'BigQuery = BigQuery.CountType type CountType 'BigQuery = BigQuery.CountType
type Column 'BigQuery = BigQuery.ColumnName type Column 'BigQuery = BigQuery.ColumnName
type ColumnPath 'BigQuery = BigQuery.ColumnName
type ScalarValue 'BigQuery = BigQuery.Value type ScalarValue 'BigQuery = BigQuery.Value
type ScalarType 'BigQuery = BigQuery.ScalarType type ScalarType 'BigQuery = BigQuery.ScalarType
type SQLExpression 'BigQuery = BigQuery.Expression type SQLExpression 'BigQuery = BigQuery.Expression
@ -117,6 +118,10 @@ instance Backend 'BigQuery where
getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the BigQuery backend" getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the BigQuery backend"
getColumnPathColumn = id
tryColumnPathToColumn = Just
instance HasSourceConfiguration 'BigQuery where instance HasSourceConfiguration 'BigQuery where
type SourceConfig 'BigQuery = BigQuery.BigQuerySourceConfig type SourceConfig 'BigQuery = BigQuery.BigQuerySourceConfig
type SourceConnConfiguration 'BigQuery = BigQuery.BigQueryConnSourceConfig type SourceConnConfiguration 'BigQuery = BigQuery.BigQueryConnSourceConfig

View File

@ -56,6 +56,7 @@ instance Backend 'DataConnector where
type NullsOrderType 'DataConnector = Unimplemented type NullsOrderType 'DataConnector = Unimplemented
type CountType 'DataConnector = DC.CountAggregate type CountType 'DataConnector = DC.CountAggregate
type Column 'DataConnector = DC.ColumnName type Column 'DataConnector = DC.ColumnName
type ColumnPath 'DataConnector = DC.ColumnPath
type ScalarValue 'DataConnector = J.Value type ScalarValue 'DataConnector = J.Value
type ScalarType 'DataConnector = DC.ScalarType type ScalarType 'DataConnector = DC.ScalarType
@ -167,6 +168,15 @@ instance Backend 'DataConnector where
getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the Data Connector backend" getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the Data Connector backend"
getColumnPathColumn = \case
DC.CPPath p -> NonEmpty.head p
DC.CPColumn c -> c
tryColumnPathToColumn = \case
DC.CPPath (column :| []) -> Just column
DC.CPColumn column -> Just column
_ -> Nothing
backendSupportsNestedObjects = pure () backendSupportsNestedObjects = pure ()
sourceSupportsSchemalessTables = sourceSupportsSchemalessTables =

View File

@ -8,7 +8,6 @@ import Control.Monad.Trans.Control
import Data.Aeson qualified as J import Data.Aeson qualified as J
import Data.Aeson.Key qualified as K import Data.Aeson.Key qualified as K
import Data.Aeson.KeyMap qualified as KM import Data.Aeson.KeyMap qualified as KM
import Data.Bifunctor (bimap)
import Data.Environment (Environment) import Data.Environment (Environment)
import Data.Has (Has (getter)) import Data.Has (Has (getter))
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
@ -71,7 +70,7 @@ import Hasura.RQL.Types.Metadata (SourceMetadata (..))
import Hasura.RQL.Types.Metadata.Backend (BackendMetadata (..)) import Hasura.RQL.Types.Metadata.Backend (BackendMetadata (..))
import Hasura.RQL.Types.Metadata.Object import Hasura.RQL.Types.Metadata.Object
import Hasura.RQL.Types.NamingCase (NamingCase) import Hasura.RQL.Types.NamingCase (NamingCase)
import Hasura.RQL.Types.Relationships.Local (ArrRelDef, ObjRelDef, RelInfo ()) import Hasura.RQL.Types.Relationships.Local (ArrRelDef, ObjRelDef, RelInfo (), RelMapping (..))
import Hasura.RQL.Types.SchemaCache (CacheRM, askSourceConfig, askSourceInfo) import Hasura.RQL.Types.SchemaCache (CacheRM, askSourceConfig, askSourceInfo)
import Hasura.RQL.Types.SchemaCache.Build import Hasura.RQL.Types.SchemaCache.Build
import Hasura.RQL.Types.SchemaCacheTypes (DependencyReason (DRTable), SchemaDependency (SchemaDependency), SchemaObjId (SOSourceObj), SourceObjId (SOITable)) import Hasura.RQL.Types.SchemaCacheTypes (DependencyReason (DRTable), SchemaDependency (SchemaDependency), SchemaObjId (SOSourceObj), SourceObjId (SOITable))
@ -474,7 +473,7 @@ buildForeignKeySet (API.ForeignKeys constraints) =
$ constraints $ constraints
& HashMap.foldMapWithKey @[RQL.T.T.ForeignKeyMetadata 'DataConnector] & HashMap.foldMapWithKey @[RQL.T.T.ForeignKeyMetadata 'DataConnector]
\constraintName API.Constraint {..} -> maybeToList do \constraintName API.Constraint {..} -> maybeToList do
let columnMapAssocList = HashMap.foldrWithKey' (\(API.ColumnName k) (API.ColumnName v) acc -> (DC.ColumnName k, DC.ColumnName v) : acc) [] _cColumnMapping let columnMapAssocList = HashMap.foldrWithKey' (\k v acc -> (Witch.from k, Witch.from v) : acc) [] $ API.unColumnPathMapping _cColumnMapping
columnMapping <- NEHashMap.fromList columnMapAssocList columnMapping <- NEHashMap.fromList columnMapAssocList
let foreignKey = let foreignKey =
RQL.T.T.ForeignKey RQL.T.T.ForeignKey
@ -786,7 +785,7 @@ convertTableMetadataToTableInfo tableName logicalModelCache RQL.T.T.DBTableMetad
constraint = constraint =
SourceConstraint SourceConstraint
{ _scForeignTable = Witch.from _fkForeignTable, { _scForeignTable = Witch.from _fkForeignTable,
_scColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> NEHashMap.toList _fkColumnMapping _scColumnMapping = RelMapping $ NEHashMap.toHashMap _fkColumnMapping
} }
in (constraintName, constraint) in (constraintName, constraint)
) )

View File

@ -23,6 +23,7 @@ module Hasura.Backends.DataConnector.Adapter.Types
TableName (..), TableName (..),
ConstraintName (..), ConstraintName (..),
ColumnName (..), ColumnName (..),
ColumnPath (..),
FunctionName (..), FunctionName (..),
FunctionReturnType (..), FunctionReturnType (..),
CountAggregate (..), CountAggregate (..),
@ -414,6 +415,41 @@ instance ToTxt ColumnName where
instance ToErrorValue ColumnName where instance ToErrorValue ColumnName where
toErrorValue = ErrorValue.squote . unColumnName toErrorValue = ErrorValue.squote . unColumnName
instance Witch.From ColumnName ColumnPath where
from = CPColumn
--------------------------------------------------------------------------------
data ColumnPath
= CPPath (NonEmpty ColumnName)
| CPColumn (ColumnName)
deriving stock (Eq, Ord, Show, Generic)
deriving (FromJSON, ToJSON, ToSchema) via AC.Autodocodec ColumnPath
deriving anyclass (Hashable, NFData)
instance HasCodec ColumnPath where
codec = AC.disjointMatchChoiceCodec pathCodec columnCodec chooser
where
pathCodec = AC.dimapCodec CPPath id (codec @(NonEmpty ColumnName))
columnCodec = AC.dimapCodec CPColumn id (codec @ColumnName)
chooser = \case
CPPath p -> Left p
CPColumn c -> Right c
instance ToJSONKey ColumnPath
instance FromJSONKey ColumnPath
instance Witch.From API.ColumnSelector ColumnPath where
from = \case
API.ColumnSelectorPath p -> CPPath $ Witch.from <$> p
API.ColumnSelectorColumn c -> CPColumn $ Witch.from c
instance Witch.From ColumnPath API.ColumnSelector where
from = \case
CPPath p -> API.ColumnSelectorPath $ Witch.from <$> p
CPColumn c -> API.ColumnSelectorColumn $ Witch.from c
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
newtype FunctionName = FunctionName {unFunctionName :: NonEmpty Text} newtype FunctionName = FunctionName {unFunctionName :: NonEmpty Text}

View File

@ -68,7 +68,7 @@ import Hasura.RQL.Types.Backend (Backend, SessionVarType, getColVals)
import Hasura.RQL.Types.BackendType import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Relationships.Local (RelInfo (..), RelTarget (..)) import Hasura.RQL.Types.Relationships.Local (RelInfo (..), RelMapping (..), RelTarget (..))
import Hasura.SQL.AnyBackend qualified as AB import Hasura.SQL.AnyBackend qualified as AB
import Hasura.SQL.Types (CollectableType (..)) import Hasura.SQL.Types (CollectableType (..))
import Hasura.Session import Hasura.Session
@ -151,7 +151,7 @@ recordTableRelationshipFromRelInfo sourceTableName RelInfo {..} = do
API.Relationship API.Relationship
{ _rTarget = API.TTable (API.TargetTable (Witch.from targetTableName)), { _rTarget = API.TTable (API.TargetTable (Witch.from targetTableName)),
_rRelationshipType = relationshipType, _rRelationshipType = relationshipType,
_rColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList riMapping _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (unRelMapping riMapping)
} }
recordRelationship recordRelationship
sourceTableName sourceTableName
@ -346,8 +346,10 @@ pushColumn :: ColumnStack -> ColumnName -> ColumnStack
pushColumn (ColumnStack stack) columnName = ColumnStack $ columnName : stack pushColumn (ColumnStack stack) columnName = ColumnStack $ columnName : stack
toColumnSelector :: ColumnStack -> ColumnName -> API.ColumnSelector toColumnSelector :: ColumnStack -> ColumnName -> API.ColumnSelector
toColumnSelector (ColumnStack []) columnName =
API.ColumnSelectorColumn $ Witch.from columnName
toColumnSelector (ColumnStack stack) columnName = toColumnSelector (ColumnStack stack) columnName =
API.ColumnSelector $ NonEmpty.reverse $ Witch.from columnName :| fmap Witch.from stack API.ColumnSelectorPath $ NonEmpty.reverse $ Witch.from columnName :| fmap Witch.from stack
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@ -214,7 +214,7 @@ fromNativeQueryArray arrRel translateFieldsAndAggregates sourceTargetName native
API.Relationship API.Relationship
{ _rTarget = TInterpolated (API.TargetInterpolatedQuery nqid), { _rTarget = TInterpolated (API.TargetInterpolatedQuery nqid),
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping arrRel) _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping arrRel)
} }
pure pure
@ -252,7 +252,7 @@ fromNativeQueryObject objRel sourceTargetName nativeQuery = do
API.Relationship API.Relationship
{ _rTarget = TInterpolated (API.TargetInterpolatedQuery nqid), { _rTarget = TInterpolated (API.TargetInterpolatedQuery nqid),
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping objRel) _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping objRel)
} }
pure pure
@ -526,7 +526,7 @@ translateAnnField targetName = \case
API.Relationship API.Relationship
{ _rTarget = API.TTable (API.TargetTable targetTable), { _rTarget = API.TTable (API.TargetTable targetTable),
_rRelationshipType = API.ObjectRelationship, _rRelationshipType = API.ObjectRelationship,
_rColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping objRel) _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping objRel)
} }
pure pure
@ -586,7 +586,7 @@ translateArrayRelationSelect targetName translateFieldsAndAggregates arrRel = do
API.Relationship API.Relationship
{ _rTarget = API.TTable (API.TargetTable (Witch.into targetTable)), { _rTarget = API.TTable (API.TargetTable (Witch.into targetTable)),
_rRelationshipType = API.ArrayRelationship, _rRelationshipType = API.ArrayRelationship,
_rColumnMapping = HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping arrRel) _rColumnMapping = API.ColumnPathMapping $ HashMap.fromList $ bimap Witch.from Witch.from <$> HashMap.toList (_aarColumnMapping arrRel)
} }
pure pure

View File

@ -86,7 +86,7 @@ fromAnnBoolExpFld =
expressions <- traverse (fromOpExpG columnInfo) opExpGs expressions <- traverse (fromOpExpG columnInfo) opExpGs
potentiallyRedacted redactionExp (AndExpression expressions) potentiallyRedacted redactionExp (AndExpression expressions)
IR.AVRemoteRelationship _ -> error "fromAnnBoolExpFld RemoteRelationship" IR.AVRemoteRelationship _ -> error "fromAnnBoolExpFld RemoteRelationship"
IR.AVRelationship IR.RelInfo {riMapping = mapping, riTarget = target} (IR.RelationshipFilters tablePerm annBoolExp) -> do IR.AVRelationship IR.RelInfo {riMapping = IR.RelMapping mapping, riTarget = target} (IR.RelationshipFilters tablePerm annBoolExp) -> do
case target of case target of
IR.RelTargetNativeQuery _ -> error "fromAnnBoolExpFld RelTargetNativeQuery" IR.RelTargetNativeQuery _ -> error "fromAnnBoolExpFld RelTargetNativeQuery"
IR.RelTargetTable table -> do IR.RelTargetTable table -> do

View File

@ -991,20 +991,20 @@ unfurlAnnotatedOrderByElement =
-- text/ntext/image. See ToQuery for more explanation. -- text/ntext/image. See ToQuery for more explanation.
_ -> Nothing _ -> Nothing
) )
IR.AOCObjectRelation IR.RelInfo {riMapping = mapping, riTarget = IR.RelTargetNativeQuery nativeQueryName} annBoolExp annOrderByElementG -> do IR.AOCObjectRelation IR.RelInfo {riMapping = IR.RelMapping mapping, riTarget = IR.RelTargetNativeQuery nativeQueryName} annBoolExp annOrderByElementG -> do
let name = T.toTxt (getNativeQueryName nativeQueryName) let name = T.toTxt (getNativeQueryName nativeQueryName)
selectFrom = TSQL.FromIdentifier name selectFrom = TSQL.FromIdentifier name
joinAliasEntity <- joinAliasEntity <-
lift (lift (generateAlias (ForOrderAlias name))) lift (lift (generateAlias (ForOrderAlias name)))
genObjectRelation mapping annBoolExp annOrderByElementG joinAliasEntity selectFrom (Left nativeQueryName) genObjectRelation mapping annBoolExp annOrderByElementG joinAliasEntity selectFrom (Left nativeQueryName)
IR.AOCObjectRelation IR.RelInfo {riMapping = mapping, riTarget = IR.RelTargetTable table} annBoolExp annOrderByElementG -> do IR.AOCObjectRelation IR.RelInfo {riMapping = IR.RelMapping mapping, riTarget = IR.RelTargetTable table} annBoolExp annOrderByElementG -> do
selectFrom <- lift (lift (fromQualifiedTable table)) selectFrom <- lift (lift (fromQualifiedTable table))
joinAliasEntity <- joinAliasEntity <-
lift (lift (generateAlias (ForOrderAlias (tableNameText table)))) lift (lift (generateAlias (ForOrderAlias (tableNameText table))))
genObjectRelation mapping annBoolExp annOrderByElementG joinAliasEntity selectFrom (Right table) genObjectRelation mapping annBoolExp annOrderByElementG joinAliasEntity selectFrom (Right table)
IR.AOCArrayAggregation IR.RelInfo {riTarget = IR.RelTargetNativeQuery _} _annBoolExp _annAggregateOrderBy -> IR.AOCArrayAggregation IR.RelInfo {riTarget = IR.RelTargetNativeQuery _} _annBoolExp _annAggregateOrderBy ->
error "unfurlAnnotatedOrderByElement RelTargetNativeQuery" error "unfurlAnnotatedOrderByElement RelTargetNativeQuery"
IR.AOCArrayAggregation IR.RelInfo {riMapping = mapping, riTarget = IR.RelTargetTable tableName} annBoolExp annAggregateOrderBy -> do IR.AOCArrayAggregation IR.RelInfo {riMapping = IR.RelMapping mapping, riTarget = IR.RelTargetTable tableName} annBoolExp annAggregateOrderBy -> do
selectFrom <- lift (lift (fromQualifiedTable tableName)) selectFrom <- lift (lift (fromQualifiedTable tableName))
let alias = aggFieldName let alias = aggFieldName
joinAliasEntity <- joinAliasEntity <-

View File

@ -40,6 +40,7 @@ instance Backend 'MSSQL where
type NullsOrderType 'MSSQL = MSSQL.NullsOrder type NullsOrderType 'MSSQL = MSSQL.NullsOrder
type CountType 'MSSQL = MSSQL.CountType type CountType 'MSSQL = MSSQL.CountType
type Column 'MSSQL = MSSQL.ColumnName type Column 'MSSQL = MSSQL.ColumnName
type ColumnPath 'MSSQL = MSSQL.ColumnName
type ScalarValue 'MSSQL = MSSQL.Value type ScalarValue 'MSSQL = MSSQL.Value
type ScalarType 'MSSQL = MSSQL.ScalarType type ScalarType 'MSSQL = MSSQL.ScalarType
type BooleanOperators 'MSSQL = MSSQL.BooleanOperators type BooleanOperators 'MSSQL = MSSQL.BooleanOperators
@ -123,6 +124,10 @@ instance Backend 'MSSQL where
getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the MSSQL backend" getColVals _ _ _ _ _ _ = throw500 "getColVals: not implemented for the MSSQL backend"
getColumnPathColumn = id
tryColumnPathToColumn = Just
instance HasSourceConfiguration 'MSSQL where instance HasSourceConfiguration 'MSSQL where
type SourceConfig 'MSSQL = MSSQL.MSSQLSourceConfig type SourceConfig 'MSSQL = MSSQL.MSSQLSourceConfig
type SourceConnConfiguration 'MSSQL = MSSQL.MSSQLConnConfiguration type SourceConnConfiguration 'MSSQL = MSSQL.MSSQLConnConfiguration

View File

@ -195,7 +195,7 @@ insertObject singleObjIns additionalColumns userInfo planVars stringifyNum tCase
afterInsertDepCols :: [ColumnInfo ('Postgres pgKind)] afterInsertDepCols :: [ColumnInfo ('Postgres pgKind)]
afterInsertDepCols = afterInsertDepCols =
flip (getColInfos @('Postgres pgKind)) allColumns flip (getColInfos @('Postgres pgKind)) allColumns
$ concatMap (HashMap.keys . riMapping . IR._riRelationInfo) allAfterInsertRels $ concatMap (HashMap.keys . unRelMapping . riMapping . IR._riRelationInfo) allAfterInsertRels
withArrRels :: withArrRels ::
Maybe (ColumnValues ('Postgres pgKind) TxtEncodedVal) -> Maybe (ColumnValues ('Postgres pgKind) TxtEncodedVal) ->
@ -258,7 +258,7 @@ insertObjRel planVars userInfo stringifyNum tCase objRelIns =
table = case riTarget relInfo of table = case riTarget relInfo of
RelTargetNativeQuery _ -> error "insertObjRel RelTargetNativeQuery" RelTargetNativeQuery _ -> error "insertObjRel RelTargetNativeQuery"
RelTargetTable tn -> tn RelTargetTable tn -> tn
mapCols = riMapping relInfo mapCols = unRelMapping $ riMapping relInfo
allCols = IR._aiTableColumns singleObjIns allCols = IR._aiTableColumns singleObjIns
rCols = HashMap.elems mapCols rCols = HashMap.elems mapCols
rColInfos = getColInfos rCols allCols rColInfos = getColInfos rCols allCols
@ -298,7 +298,7 @@ insertArrRel resCols userInfo planVars stringifyNum tCase arrRelIns =
$ throw500 "affected_rows not returned in array rel insert" $ throw500 "affected_rows not returned in array rel insert"
where where
IR.RelationInsert multiObjIns relInfo = arrRelIns IR.RelationInsert multiObjIns relInfo = arrRelIns
mapping = riMapping relInfo mapping = unRelMapping $ riMapping relInfo
mutOutput = IR.MOutMultirowFields [("affected_rows", IR.MCount)] mutOutput = IR.MOutMultirowFields [("affected_rows", IR.MCount)]
-- | Validate an insert object based on insert columns, -- | Validate an insert object based on insert columns,
@ -325,7 +325,7 @@ validateInsert insCols objRels addCols = do
<> " columns as their values are already being determined by parent insert" <> " columns as their values are already being determined by parent insert"
forM_ objRels $ \relInfo -> do forM_ objRels $ \relInfo -> do
let lCols = HashMap.keys $ riMapping relInfo let lCols = HashMap.keys $ unRelMapping $ riMapping relInfo
relName = riName relInfo relName = riName relInfo
relNameTxt = relNameToTxt relName relNameTxt = relNameToTxt relName
lColConflicts = lCols `intersect` (addCols <> insCols) lColConflicts = lCols `intersect` (addCols <> insCols)

View File

@ -323,7 +323,7 @@ instance
let mappings :: HashMap Postgres.PGCol Postgres.PGCol let mappings :: HashMap Postgres.PGCol Postgres.PGCol
mappings = NEHashMap.toHashMap _fkColumnMapping mappings = NEHashMap.toHashMap _fkColumnMapping
pure (_cName _fkConstraint, SourceConstraint _fkForeignTable mappings) pure (_cName _fkConstraint, SourceConstraint _fkForeignTable $ RelMapping mappings)
pure pure
SourceTableInfo SourceTableInfo

View File

@ -103,6 +103,7 @@ instance
type NullsOrderType ('Postgres pgKind) = Postgres.NullsOrder type NullsOrderType ('Postgres pgKind) = Postgres.NullsOrder
type CountType ('Postgres pgKind) = Postgres.CountAggregate pgKind type CountType ('Postgres pgKind) = Postgres.CountAggregate pgKind
type Column ('Postgres pgKind) = Postgres.PGCol type Column ('Postgres pgKind) = Postgres.PGCol
type ColumnPath ('Postgres pgKind) = Postgres.PGCol
type ScalarValue ('Postgres pgKind) = Postgres.PGScalarValue type ScalarValue ('Postgres pgKind) = Postgres.PGScalarValue
type ScalarType ('Postgres pgKind) = Postgres.PGScalarType type ScalarType ('Postgres pgKind) = Postgres.PGScalarType
type BooleanOperators ('Postgres pgKind) = Postgres.BooleanOperators type BooleanOperators ('Postgres pgKind) = Postgres.BooleanOperators
@ -177,6 +178,10 @@ instance
getColVals = Postgres.getPGColValues getColVals = Postgres.getPGColValues
getColumnPathColumn = id
tryColumnPathToColumn = Just
instance instance
( HasTag ('Postgres pgKind) ( HasTag ('Postgres pgKind)
) => ) =>

View File

@ -375,12 +375,12 @@ translateAggPredArguments predArgs relTableNameIdentifier userInfo =
) )
cols cols
translateTableRelationship :: (Monad m) => HashMap PGCol PGCol -> TableIdentifier -> BoolExpM m S.BoolExp translateTableRelationship :: (Monad m) => RelMapping ('Postgres pgKind) -> TableIdentifier -> BoolExpM m S.BoolExp
translateTableRelationship colMapping relTableNameIdentifier = do translateTableRelationship colMapping relTableNameIdentifier = do
BoolExpCtx {currTableReference} <- ask BoolExpCtx {currTableReference} <- ask
pure pure
$ sqlAnd $ sqlAnd
$ flip map (HashMap.toList colMapping) $ flip map (HashMap.toList $ unRelMapping colMapping)
$ \(lCol, rCol) -> $ \(lCol, rCol) ->
S.BECompare S.BECompare
S.SEQ S.SEQ

View File

@ -132,7 +132,7 @@ processOrderByItems userInfo sourcePrefix' selectSourceQual fieldAlias' similarA
$ S.mkQIdenExp baseTableIdentifier $ S.mkQIdenExp baseTableIdentifier
$ ciColumn pgColInfo $ ciColumn pgColInfo
AOCObjectRelation relInfo relFilter rest -> withWriteObjectRelation $ do AOCObjectRelation relInfo relFilter rest -> withWriteObjectRelation $ do
let RelInfo {riName = relName, riMapping = colMapping, riTarget = relTarget} = relInfo let RelInfo {riName = relName, riMapping = RelMapping colMapping, riTarget = relTarget} = relInfo
relSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName relSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName
fieldName = mkOrderByFieldName relName fieldName = mkOrderByFieldName relName
case relTarget of case relTarget of
@ -153,7 +153,7 @@ processOrderByItems userInfo sourcePrefix' selectSourceQual fieldAlias' similarA
S.mkQIdenExp relSourcePrefix relOrderByAlias S.mkQIdenExp relSourcePrefix relOrderByAlias
) )
AOCArrayAggregation relInfo relFilter aggOrderBy -> withWriteArrayRelation $ do AOCArrayAggregation relInfo relFilter aggOrderBy -> withWriteArrayRelation $ do
let RelInfo {riName = relName, riMapping = colMapping, riTarget = relTarget} = relInfo let RelInfo {riName = relName, riMapping = RelMapping colMapping, riTarget = relTarget} = relInfo
case relTarget of case relTarget of
RelTargetNativeQuery _ -> error "processAnnotatedOrderByElement RelTargetNativeQuery (AOCArrayAggregation)" RelTargetNativeQuery _ -> error "processAnnotatedOrderByElement RelTargetNativeQuery (AOCArrayAggregation)"
RelTargetTable relTable -> do RelTargetTable relTable -> do

View File

@ -187,7 +187,7 @@ convertRemoteSourceRelationship ::
forall b. forall b.
(Backend b) => (Backend b) =>
-- | Join columns for the relationship -- | Join columns for the relationship
HashMap (Column b) (Column b) -> HashMap (ColumnPath b) (ColumnPath b) ->
-- | The LHS of the join, this is the expression which selects from json -- | The LHS of the join, this is the expression which selects from json
-- objects -- objects
SelectFromG b (UnpreparedValue b) -> SelectFromG b (UnpreparedValue b) ->

View File

@ -1560,7 +1560,7 @@ relationshipField table ri@RelInfo {riTarget = RelTargetTable otherTableName} =
RelTargetTable tn -> Just tn RelTargetTable tn -> Just tn
_ -> Nothing _ -> Nothing
in if (remoteTableName == Just table) in if (remoteTableName == Just table)
&& (riMapping remoteRI `HashMap.isInverseOf` riMapping ri) && (unRelMapping (riMapping remoteRI) `HashMap.isInverseOf` unRelMapping (riMapping ri))
&& (thisTablePerm == rfFilter) && (thisTablePerm == rfFilter)
then BoolAnd [] then BoolAnd []
else x else x
@ -1610,7 +1610,7 @@ relationshipField table ri@RelInfo {riTarget = RelTargetTable otherTableName} =
nullable <- case (riIsManual ri, riInsertOrder ri) of nullable <- case (riIsManual ri, riInsertOrder ri) of
-- Automatically generated forward relationship -- Automatically generated forward relationship
(False, BeforeParent) -> do (False, BeforeParent) -> do
let columns = HashMap.keys $ riMapping ri let columns = fmap (getColumnPathColumn @b) $ HashMap.keys $ unRelMapping $ riMapping ri
fieldInfoMap = _tciFieldInfoMap $ _tiCoreInfo tableInfo fieldInfoMap = _tciFieldInfoMap $ _tiCoreInfo tableInfo
findColumn col = HashMap.lookup (fromCol @b col) fieldInfoMap ^? _Just . _FIColumn . _SCIScalarColumn findColumn col = HashMap.lookup (fromCol @b col) fieldInfoMap ^? _Just . _FIColumn . _SCIScalarColumn
-- Fetch information about the referencing columns of the foreign key -- Fetch information about the referencing columns of the foreign key
@ -1627,7 +1627,7 @@ relationshipField table ri@RelInfo {riTarget = RelTargetTable otherTableName} =
$ P.subselection_ relFieldName desc selectionSetParser $ P.subselection_ relFieldName desc selectionSetParser
<&> \fields -> <&> \fields ->
IR.AFObjectRelation IR.AFObjectRelation
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable
$ IR.AnnObjectSelectG fields (IR.FromTable otherTableName) $ IR.AnnObjectSelectG fields (IR.FromTable otherTableName)
$ deduplicatePermissions $ deduplicatePermissions
$ IR._tpFilter $ IR._tpFilter
@ -1639,7 +1639,7 @@ relationshipField table ri@RelInfo {riTarget = RelTargetTable otherTableName} =
otherTableParser <&> \selectExp -> otherTableParser <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable
$ deduplicatePermissions' selectExp $ deduplicatePermissions' selectExp
relAggFieldName = applyFieldNameCaseCust tCase $ relFieldName <> Name.__aggregate relAggFieldName = applyFieldNameCaseCust tCase $ relFieldName <> Name.__aggregate
relAggDesc = Just $ G.Description "An aggregate relationship" relAggDesc = Just $ G.Description "An aggregate relationship"
@ -1658,8 +1658,8 @@ relationshipField table ri@RelInfo {riTarget = RelTargetTable otherTableName} =
pure pure
$ catMaybes $ catMaybes
[ Just arrayRelField, [ Just arrayRelField,
fmap (IR.AFArrayRelation . IR.ASAggregate . IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable) <$> remoteAggField, fmap (IR.AFArrayRelation . IR.ASAggregate . IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable) <$> remoteAggField,
fmap (IR.AFArrayRelation . IR.ASConnection . IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable) <$> remoteConnectionField fmap (IR.AFArrayRelation . IR.ASConnection . IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable) <$> remoteConnectionField
] ]
relationshipField _table ri@RelInfo {riTarget = RelTargetNativeQuery nativeQueryName} = runMaybeT do relationshipField _table ri@RelInfo {riTarget = RelTargetNativeQuery nativeQueryName} = runMaybeT do
relFieldName <- lift $ textToName $ relNameToTxt $ riName ri relFieldName <- lift $ textToName $ relNameToTxt $ riName ri
@ -1680,7 +1680,7 @@ relationshipField _table ri@RelInfo {riTarget = RelTargetNativeQuery nativeQuery
$ pure $ pure
$ nativeQueryParser $ nativeQueryParser
<&> \selectExp -> <&> \selectExp ->
IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (riMapping ri) nullability selectExp) IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) nullability selectExp)
ArrRel -> do ArrRel -> do
nativeQueryInfo <- askNativeQueryInfo nativeQueryName nativeQueryInfo <- askNativeQueryInfo nativeQueryName
@ -1697,4 +1697,4 @@ relationshipField _table ri@RelInfo {riTarget = RelTargetNativeQuery nativeQuery
<&> \selectExp -> <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) innerNullability selectExp $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) innerNullability selectExp

View File

@ -48,7 +48,7 @@ import Hasura.RQL.IR.Value (Provenance (FreshVar), UnpreparedValue (UVParameter)
import Hasura.RQL.Types.Column qualified as Column import Hasura.RQL.Types.Column qualified as Column
import Hasura.RQL.Types.Common (RelType (..), relNameToTxt) import Hasura.RQL.Types.Common (RelType (..), relNameToTxt)
import Hasura.RQL.Types.Metadata.Object qualified as MO import Hasura.RQL.Types.Metadata.Object qualified as MO
import Hasura.RQL.Types.Relationships.Local (Nullable (..), RelInfo (..), RelTarget (..)) import Hasura.RQL.Types.Relationships.Local (Nullable (..), RelInfo (..), RelMapping (..), RelTarget (..))
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.RQL.Types.Source import Hasura.RQL.Types.Source
( SourceInfo (_siCustomization, _siName), ( SourceInfo (_siCustomization, _siName),
@ -328,7 +328,7 @@ nativeQueryRelationshipField ri | riType ri == ObjRel = runMaybeT do
pure pure
$ nativeQueryParser $ nativeQueryParser
<&> \selectExp -> <&> \selectExp ->
IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (riMapping ri) nullability selectExp) IR.AFObjectRelation (IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) nullability selectExp)
RelTargetTable otherTableName -> do RelTargetTable otherTableName -> do
let desc = Just $ G.Description "An object relationship" let desc = Just $ G.Description "An object relationship"
roleName <- retrieve scRole roleName <- retrieve scRole
@ -339,7 +339,7 @@ nativeQueryRelationshipField ri | riType ri == ObjRel = runMaybeT do
$ P.subselection_ relFieldName desc selectionSetParser $ P.subselection_ relFieldName desc selectionSetParser
<&> \fields -> <&> \fields ->
IR.AFObjectRelation IR.AFObjectRelation
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable
$ IR.AnnObjectSelectG fields (IR.FromTable otherTableName) $ IR.AnnObjectSelectG fields (IR.FromTable otherTableName)
$ IR._tpFilter $ IR._tpFilter
$ tablePermissionsInfo remotePerms $ tablePermissionsInfo remotePerms
@ -361,7 +361,7 @@ nativeQueryRelationshipField ri = do
<&> \selectExp -> <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) innerNullability selectExp $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) innerNullability selectExp
RelTargetTable otherTableName -> runMaybeT $ do RelTargetTable otherTableName -> runMaybeT $ do
let arrayRelDesc = Just $ G.Description "An array relationship" let arrayRelDesc = Just $ G.Description "An array relationship"
@ -371,6 +371,6 @@ nativeQueryRelationshipField ri = do
otherTableParser <&> \selectExp -> otherTableParser <&> \selectExp ->
IR.AFArrayRelation IR.AFArrayRelation
$ IR.ASSimple $ IR.ASSimple
$ IR.AnnRelationSelectG (riName ri) (riMapping ri) Nullable $ IR.AnnRelationSelectG (riName ri) (unRelMapping $ riMapping ri) Nullable
$ selectExp $ selectExp
pure arrayRelField pure arrayRelField

View File

@ -135,14 +135,15 @@ defaultBuildObjectRelationshipInfo ::
m (RelInfo b, Seq SchemaDependency) m (RelInfo b, Seq SchemaDependency)
defaultBuildObjectRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case ru of defaultBuildObjectRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case ru of
RUManual (RelManualNativeQueryConfig (RelManualNativeQueryConfigC {rmnNativeQueryName = refqt, rmnCommon = common})) -> do RUManual (RelManualNativeQueryConfig (RelManualNativeQueryConfigC {rmnNativeQueryName = refqt, rmnCommon = common})) -> do
let (lCols, rCols) = unzip $ HashMap.toList $ rmColumns common let (lCols, rCols) = unzip $ HashMap.toList $ unRelMapping $ rmColumns common
io = fromMaybe BeforeParent $ rmInsertOrder common io = fromMaybe BeforeParent $ rmInsertOrder common
mkNativeQueryDependency nativeQueryName reason col = mkNativeQueryDependency nativeQueryName reason col =
SchemaDependency SchemaDependency
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOINativeQueryObj @b nativeQueryName $ SOINativeQueryObj @b nativeQueryName
$ NQOCol @b col $ NQOCol @b
$ getColumnPathColumn @b col
) )
reason reason
mkDependency tableName reason col = mkDependency tableName reason col =
@ -150,7 +151,8 @@ defaultBuildObjectRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b tableName $ SOITableObj @b tableName
$ TOCol @b col $ TOCol @b
$ getColumnPathColumn @b col
) )
reason reason
dependencies = dependencies =
@ -158,14 +160,15 @@ defaultBuildObjectRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
<> (mkNativeQueryDependency refqt DRRightColumn <$> Seq.fromList rCols) <> (mkNativeQueryDependency refqt DRRightColumn <$> Seq.fromList rCols)
pure (RelInfo rn ObjRel (rmColumns common) (RelTargetNativeQuery refqt) True io, dependencies) pure (RelInfo rn ObjRel (rmColumns common) (RelTargetNativeQuery refqt) True io, dependencies)
RUManual (RelManualTableConfig (RelManualTableConfigC {rmtTable = refqt, rmtCommon = common})) -> do RUManual (RelManualTableConfig (RelManualTableConfigC {rmtTable = refqt, rmtCommon = common})) -> do
let (lCols, rCols) = unzip $ HashMap.toList $ rmColumns common let (lCols, rCols) = unzip $ HashMap.toList $ unRelMapping $ rmColumns common
io = fromMaybe BeforeParent $ rmInsertOrder common io = fromMaybe BeforeParent $ rmInsertOrder common
mkDependency tableName reason col = mkDependency tableName reason col =
SchemaDependency SchemaDependency
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b tableName $ SOITableObj @b tableName
$ TOCol @b col $ TOCol @b
$ getColumnPathColumn @b col
) )
reason reason
dependencies = dependencies =
@ -195,8 +198,8 @@ defaultBuildObjectRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
) )
DRRemoteTable DRRemoteTable
] ]
<> (drUsingColumnDep @b source qt <$> Seq.fromList (toList columns)) <> (drUsingColumnDep @b source qt <$> Seq.fromList (toList $ getColumnPathColumn @b <$> columns))
pure (RelInfo rn ObjRel (NEHashMap.toHashMap colMap) (RelTargetTable foreignTable) False BeforeParent, dependencies) pure (RelInfo rn ObjRel (RelMapping $ NEHashMap.toHashMap colMap) (RelTargetTable foreignTable) False BeforeParent, dependencies)
RUFKeyOn (RemoteTable remoteTable remoteCols) -> RUFKeyOn (RemoteTable remoteTable remoteCols) ->
mkFkeyRel ObjRel AfterParent source rn qt remoteTable remoteCols foreignKeys mkFkeyRel ObjRel AfterParent source rn qt remoteTable remoteCols foreignKeys
@ -219,7 +222,8 @@ nativeQueryRelationshipSetup sourceName nativeQueryName relType (RelDef relName
( SOSourceObj sourceName ( SOSourceObj sourceName
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOINativeQueryObj @b refqt $ SOINativeQueryObj @b refqt
$ NQOCol @b c $ NQOCol @b
$ getColumnPathColumn @b c
) )
DRRightColumn DRRightColumn
) )
@ -231,12 +235,13 @@ nativeQueryRelationshipSetup sourceName nativeQueryName relType (RelDef relName
( SOSourceObj sourceName ( SOSourceObj sourceName
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b refqt $ SOITableObj @b refqt
$ TOCol @b c $ TOCol @b
$ getColumnPathColumn @b c
) )
DRRightColumn DRRightColumn
) )
let (lCols, rCols) = unzip $ HashMap.toList $ rmColumns common let (lCols, rCols) = unzip $ HashMap.toList $ unRelMapping $ rmColumns common
io = case relType of io = case relType of
ObjRel -> fromMaybe BeforeParent $ rmInsertOrder common ObjRel -> fromMaybe BeforeParent $ rmInsertOrder common
ArrRel -> AfterParent ArrRel -> AfterParent
@ -247,7 +252,8 @@ nativeQueryRelationshipSetup sourceName nativeQueryName relType (RelDef relName
( SOSourceObj sourceName ( SOSourceObj sourceName
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOINativeQueryObj @b nativeQueryName $ SOINativeQueryObj @b nativeQueryName
$ NQOCol @b c $ NQOCol @b
$ getColumnPathColumn @b c
) )
DRLeftColumn DRLeftColumn
) )
@ -266,7 +272,7 @@ defaultBuildArrayRelationshipInfo ::
m (RelInfo b, Seq SchemaDependency) m (RelInfo b, Seq SchemaDependency)
defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case ru of defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case ru of
RUManual (RelManualNativeQueryConfig (RelManualNativeQueryConfigC {rmnNativeQueryName = refqt, rmnCommon = common})) -> do RUManual (RelManualNativeQueryConfig (RelManualNativeQueryConfigC {rmnNativeQueryName = refqt, rmnCommon = common})) -> do
let (lCols, rCols) = unzip $ HashMap.toList $ rmColumns common let (lCols, rCols) = unzip $ HashMap.toList $ unRelMapping $ rmColumns common
deps = deps =
( fmap ( fmap
( \c -> ( \c ->
@ -274,7 +280,8 @@ defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b qt $ SOITableObj @b qt
$ TOCol @b c $ TOCol @b
$ getColumnPathColumn @b c
) )
DRLeftColumn DRLeftColumn
) )
@ -286,14 +293,15 @@ defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOINativeQueryObj @b refqt $ SOINativeQueryObj @b refqt
$ NQOCol @b c $ NQOCol @b
$ getColumnPathColumn @b c
) )
DRRightColumn DRRightColumn
) )
(Seq.fromList rCols) (Seq.fromList rCols)
pure (RelInfo rn ArrRel (rmColumns common) (RelTargetNativeQuery refqt) True AfterParent, deps) pure (RelInfo rn ArrRel (rmColumns common) (RelTargetNativeQuery refqt) True AfterParent, deps)
RUManual (RelManualTableConfig (RelManualTableConfigC {rmtTable = refqt, rmtCommon = common})) -> do RUManual (RelManualTableConfig (RelManualTableConfigC {rmtTable = refqt, rmtCommon = common})) -> do
let (lCols, rCols) = unzip $ HashMap.toList $ rmColumns common let (lCols, rCols) = unzip $ HashMap.toList $ unRelMapping $ rmColumns common
deps = deps =
( fmap ( fmap
( \c -> ( \c ->
@ -301,7 +309,8 @@ defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b qt $ SOITableObj @b qt
$ TOCol @b c $ TOCol @b
$ getColumnPathColumn @b c
) )
DRLeftColumn DRLeftColumn
) )
@ -313,7 +322,8 @@ defaultBuildArrayRelationshipInfo source foreignKeys qt (RelDef rn ru _) = case
( SOSourceObj source ( SOSourceObj source
$ AB.mkAnyBackend $ AB.mkAnyBackend
$ SOITableObj @b refqt $ SOITableObj @b refqt
$ TOCol @b c $ TOCol @b
$ getColumnPathColumn @b c
) )
DRRightColumn DRRightColumn
) )
@ -332,7 +342,7 @@ mkFkeyRel ::
RelName -> RelName ->
TableName b -> TableName b ->
TableName b -> TableName b ->
NonEmpty (Column b) -> NonEmpty (ColumnPath b) ->
HashMap (TableName b) (HashSet (ForeignKey b)) -> HashMap (TableName b) (HashSet (ForeignKey b)) ->
m (RelInfo b, Seq SchemaDependency) m (RelInfo b, Seq SchemaDependency)
mkFkeyRel relType io source rn sourceTable remoteTable remoteColumns foreignKeys = do mkFkeyRel relType io source rn sourceTable remoteTable remoteColumns foreignKeys = do
@ -358,17 +368,18 @@ mkFkeyRel relType io source rn sourceTable remoteTable remoteColumns foreignKeys
DRRemoteTable DRRemoteTable
] ]
<> ( drUsingColumnDep @b source remoteTable <> ( drUsingColumnDep @b source remoteTable
<$> Seq.fromList (toList remoteColumns) <$> Seq.fromList (toList $ getColumnPathColumn @b <$> remoteColumns)
) )
pure (RelInfo rn relType (reverseMap (NEHashMap.toHashMap colMap)) (RelTargetTable remoteTable) False io, dependencies) pure (RelInfo rn relType (RelMapping $ reverseMap $ NEHashMap.toHashMap colMap) (RelTargetTable remoteTable) False io, dependencies)
where where
reverseMap :: (Hashable y) => HashMap x y -> HashMap y x reverseMap :: (Hashable y) => HashMap x y -> HashMap y x
reverseMap = HashMap.fromList . fmap swap . HashMap.toList reverseMap = HashMap.fromList . fmap swap . HashMap.toList
-- | Try to find a foreign key constraint, identifying a constraint by its set of columns -- | Try to find a foreign key constraint, identifying a constraint by its set of columns
getRequiredFkey :: getRequiredFkey ::
forall m b.
(QErrM m, Backend b) => (QErrM m, Backend b) =>
NonEmpty (Column b) -> NonEmpty (ColumnPath b) ->
[ForeignKey b] -> [ForeignKey b] ->
m (ForeignKey b) m (ForeignKey b)
getRequiredFkey cols fkeys = getRequiredFkey cols fkeys =

View File

@ -36,10 +36,11 @@ import Hasura.Prelude
import Hasura.RQL.Types.Backend import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Metadata.Backend import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.Relationships.Local (RelInfo (riMapping, riTarget), RelTarget (..)) import Hasura.RQL.Types.Relationships.Local (RelInfo (riMapping, riTarget), RelMapping (..), RelTarget (..))
import Hasura.RQL.Types.SchemaCache import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCache.Build import Hasura.RQL.Types.SchemaCache.Build
import Hasura.Table.Cache (ForeignKey, UniqueConstraint, _cName, _fkColumnMapping, _fkConstraint, _fkForeignTable, _ucColumns) import Hasura.Table.Cache (ForeignKey, UniqueConstraint, _cName, _fkColumnMapping, _fkConstraint, _fkForeignTable, _ucColumns)
import Witch qualified
-- | Datatype used by Metadata API to represent Request for Suggested Relationships -- | Datatype used by Metadata API to represent Request for Suggested Relationships
data SuggestRels b = SuggestRels data SuggestRels b = SuggestRels
@ -102,7 +103,7 @@ instance (Backend b) => HasCodec (Relationship b) where
data Mapping b = Mapping data Mapping b = Mapping
{ mTable :: TableName b, { mTable :: TableName b,
mColumns :: [Column b], mColumns :: [ColumnPath b],
mConstraintName :: Maybe J.Value mConstraintName :: Maybe J.Value
} }
deriving (Generic) deriving (Generic)
@ -133,7 +134,7 @@ suggestRelsFK ::
HashMap (TableName b) (TableCoreInfo b) -> HashMap (TableName b) (TableCoreInfo b) ->
TableName b -> TableName b ->
HashSet (UniqueConstraint b) -> HashSet (UniqueConstraint b) ->
H.HashSet (TableName b, HashMap (Column b) (Column b)) -> H.HashSet (TableName b, HashMap (ColumnPath b) (ColumnPath b)) ->
(TableName b -> Bool) -> (TableName b -> Bool) ->
ForeignKey b -> ForeignKey b ->
[Relationship b] [Relationship b]
@ -145,6 +146,7 @@ suggestRelsFK omitTracked tables name uniqueConstraints tracked predicate foreig
where where
toTracked = H.member (relatedTableName, columnRelationships) tracked toTracked = H.member (relatedTableName, columnRelationships) tracked
fromTracked = H.member (name, invert columnRelationships) trackedBack fromTracked = H.member (name, invert columnRelationships) trackedBack
toRelationship, fromRelationship :: Relationship b
toRelationship = toRelationship =
Relationship Relationship
{ rType = ObjRel, { rType = ObjRel,
@ -157,10 +159,10 @@ suggestRelsFK omitTracked tables name uniqueConstraints tracked predicate foreig
rTo = Mapping {mTable = name, mColumns = localColumns, mConstraintName = Just constraintName}, rTo = Mapping {mTable = name, mColumns = localColumns, mConstraintName = Just constraintName},
rFrom = Mapping {mTable = relatedTableName, mColumns = relatedColumns, mConstraintName = Nothing} rFrom = Mapping {mTable = relatedTableName, mColumns = relatedColumns, mConstraintName = Nothing}
} }
columnRelationships = MapNE.toHashMap (_fkColumnMapping foreignKey) columnRelationships = MapNE.toHashMap $ _fkColumnMapping foreignKey
localColumns = HashMap.keys columnRelationships localColumns = HashMap.keys columnRelationships
relatedColumns = HashMap.elems columnRelationships relatedColumns = HashMap.elems columnRelationships
uniqueConstraintColumns = H.map _ucColumns uniqueConstraints uniqueConstraintColumns = H.map (H.map Witch.from . _ucColumns) uniqueConstraints
relatedTableName = _fkForeignTable foreignKey relatedTableName = _fkForeignTable foreignKey
relatedTable = HashMap.lookup relatedTableName tables relatedTable = HashMap.lookup relatedTableName tables
constraintName = J.toJSON (_cName (_fkConstraint foreignKey)) constraintName = J.toJSON (_cName (_fkConstraint foreignKey))
@ -174,10 +176,10 @@ suggestRelsFK omitTracked tables name uniqueConstraints tracked predicate foreig
-- we're only interested in suggesting table-based relationships for now -- we're only interested in suggesting table-based relationships for now
getRelationshipsInputs :: getRelationshipsInputs ::
RelInfo b -> RelInfo b ->
Maybe (TableName b, HashMap (Column b) (Column b)) Maybe (TableName b, HashMap (ColumnPath b) (ColumnPath b))
getRelationshipsInputs ri = getRelationshipsInputs ri =
case riTarget ri of case riTarget ri of
RelTargetTable tn -> Just (tn, riMapping ri) RelTargetTable tn -> Just (tn, unRelMapping $ riMapping ri)
_ -> Nothing _ -> Nothing
suggestRelsTable :: suggestRelsTable ::

View File

@ -289,7 +289,8 @@ processTablesDiff ::
( MonadError QErr m, ( MonadError QErr m,
CacheRM m, CacheRM m,
MonadWriter MetadataModifier m, MonadWriter MetadataModifier m,
BackendMetadata b BackendMetadata b,
Column b ~ ColumnPath b
) => ) =>
SourceName -> SourceName ->
TableCache b -> TableCache b ->
@ -313,7 +314,8 @@ alterTableInMetadata ::
( MonadError QErr m, ( MonadError QErr m,
CacheRM m, CacheRM m,
MonadWriter MetadataModifier m, MonadWriter MetadataModifier m,
BackendMetadata b BackendMetadata b,
Column b ~ ColumnPath b
) => ) =>
SourceName -> SourceName ->
TableCoreInfo b -> TableCoreInfo b ->
@ -387,7 +389,8 @@ alterColumnsInMetadata ::
( MonadError QErr m, ( MonadError QErr m,
CacheRM m, CacheRM m,
MonadWriter MetadataModifier m, MonadWriter MetadataModifier m,
BackendMetadata b BackendMetadata b,
Column b ~ ColumnPath b
) => ) =>
SourceName -> SourceName ->
[(RawColumnInfo b, RawColumnInfo b)] -> [(RawColumnInfo b, RawColumnInfo b)] ->

View File

@ -40,7 +40,9 @@ resolveEnumReferences enumTables =
where where
resolveEnumReference :: ForeignKey b -> Maybe (Column b, EnumReference b) resolveEnumReference :: ForeignKey b -> Maybe (Column b, EnumReference b)
resolveEnumReference foreignKey = do resolveEnumReference foreignKey = do
[(localColumn, foreignColumn)] <- pure $ NEHashMap.toList (_fkColumnMapping @b foreignKey) [(localColumnPath, foreignColumnPath)] <- pure $ NEHashMap.toList (_fkColumnMapping @b foreignKey)
localColumn <- tryColumnPathToColumn @b localColumnPath
foreignColumn <- tryColumnPathToColumn @b foreignColumnPath
let foreignKeyTableName = _fkForeignTable foreignKey let foreignKeyTableName = _fkForeignTable foreignKey
(primaryKey, tConfig, enumValues) <- HashMap.lookup foreignKeyTableName enumTables (primaryKey, tConfig, enumValues) <- HashMap.lookup foreignKeyTableName enumTables
let tableCustomName = _tcCustomName tConfig let tableCustomName = _tcCustomName tConfig

View File

@ -933,4 +933,4 @@ recreateSystemMetadata = do
$ RelManualTableConfig $ RelManualTableConfig
$ RelManualTableConfigC $ RelManualTableConfigC
(QualifiedObject schemaName tableName) (QualifiedObject schemaName tableName)
(RelManualCommon (HashMap.fromList columns) Nothing) (RelManualCommon (RelMapping $ HashMap.fromList columns) Nothing)

View File

@ -162,7 +162,8 @@ renameColumnInMetadata ::
( MonadError QErr m, ( MonadError QErr m,
CacheRM m, CacheRM m,
MonadWriter MetadataModifier m, MonadWriter MetadataModifier m,
BackendMetadata b BackendMetadata b,
Column b ~ ColumnPath b
) => ) =>
Column b -> Column b ->
Column b -> Column b ->
@ -532,7 +533,7 @@ updateColExp qt rf (ColExp fld val) =
-- rename columns in relationship definitions -- rename columns in relationship definitions
updateColInRel :: updateColInRel ::
forall b m. forall b m.
(CacheRM m, MonadWriter MetadataModifier m, BackendMetadata b) => (CacheRM m, MonadWriter MetadataModifier m, BackendMetadata b, Column b ~ ColumnPath b) =>
SourceName -> SourceName ->
TableName b -> TableName b ->
RelName -> RelName ->
@ -681,7 +682,7 @@ updateTableInRemoteRelationshipRHS source tableName remoteRelationshipName (_, n
.~ toJSON newTableName .~ toJSON newTableName
updateColInObjRel :: updateColInObjRel ::
(Backend b) => (Backend b, Column b ~ ColumnPath b) =>
TableName b -> TableName b ->
TableName b -> TableName b ->
RenameCol b -> RenameCol b ->
@ -694,7 +695,7 @@ updateColInObjRel fromQT toQT rnCol = \case
RUManual $ updateRelManualConfig fromQT toQT rnCol manConfig RUManual $ updateRelManualConfig fromQT toQT rnCol manConfig
updateRelChoice :: updateRelChoice ::
(Backend b) => (Backend b, Column b ~ ColumnPath b) =>
TableName b -> TableName b ->
TableName b -> TableName b ->
RenameCol b -> RenameCol b ->
@ -706,7 +707,7 @@ updateRelChoice fromQT toQT rnCol =
RemoteTable t c -> RemoteTable t (getNewCol rnCol toQT c) RemoteTable t c -> RemoteTable t (getNewCol rnCol toQT c)
updateColInArrRel :: updateColInArrRel ::
(Backend b) => (Backend b, Column b ~ ColumnPath b) =>
TableName b -> TableName b ->
TableName b -> TableName b ->
RenameCol b -> RenameCol b ->
@ -718,8 +719,6 @@ updateColInArrRel fromQT toQT rnCol = \case
in RUFKeyOn $ ArrRelUsingFKeyOn t updCol in RUFKeyOn $ ArrRelUsingFKeyOn t updCol
RUManual manConfig -> RUManual $ updateRelManualConfig fromQT toQT rnCol manConfig RUManual manConfig -> RUManual $ updateRelManualConfig fromQT toQT rnCol manConfig
type ColMap b = HashMap (Column b) (Column b)
getNewCol :: getNewCol ::
forall b f. forall b f.
(Backend b) => (Backend b) =>
@ -741,7 +740,7 @@ getNewCol rnCol qt cols =
updateRelManualConfig :: updateRelManualConfig ::
forall b. forall b.
(Backend b) => (Backend b, Column b ~ ColumnPath b) =>
TableName b -> TableName b ->
TableName b -> TableName b ->
RenameCol b -> RenameCol b ->
@ -754,14 +753,14 @@ updateRelManualConfig fromQT toQT rnCol (RelManualNativeQueryConfig (RelManualNa
updateColMap :: updateColMap ::
forall b. forall b.
(Backend b) => (Backend b, Column b ~ ColumnPath b) =>
TableName b -> TableName b ->
TableName b -> TableName b ->
RenameCol b -> RenameCol b ->
ColMap b -> RelMapping b ->
ColMap b RelMapping b
updateColMap fromQT toQT rnCol = updateColMap fromQT toQT rnCol =
HashMap.fromList . map (modCol fromQT *** modCol toQT) . HashMap.toList RelMapping . HashMap.fromList . map (modCol fromQT *** modCol toQT) . HashMap.toList . unRelMapping
where where
RenameItem qt oCol nCol = rnCol RenameItem qt oCol nCol = rnCol
modCol colQt col = if colQt == qt && col == oCol then nCol else col modCol colQt col = if colQt == qt && col == oCol then nCol else col

View File

@ -286,7 +286,7 @@ convExtRel sqlGen fieldInfoMap relName mAlias selQ sessVarBldr prepValBldr = do
relInfo <- relInfo <-
withPathK "name" withPathK "name"
$ askRelType fieldInfoMap relName pgWhenRelErr $ askRelType fieldInfoMap relName pgWhenRelErr
let (RelInfo {riType = relTy, riMapping = colMapping, riTarget = relTarget}) = relInfo let (RelInfo {riType = relTy, riMapping = RelMapping colMapping, riTarget = relTarget}) = relInfo
relTableName <- case relTarget of relTableName <- case relTarget of
RelTargetNativeQuery _ -> error "convExtRel RelTargetNativeQuery" RelTargetNativeQuery _ -> error "convExtRel RelTargetNativeQuery"
RelTargetTable tn -> pure tn RelTargetTable tn -> pure tn

View File

@ -18,7 +18,7 @@ import Hasura.RQL.Types.Relationships.Local (Nullable)
data AnnRelationSelectG (b :: BackendType) a = AnnRelationSelectG data AnnRelationSelectG (b :: BackendType) a = AnnRelationSelectG
{ _aarRelationshipName :: RelName, -- Relationship name { _aarRelationshipName :: RelName, -- Relationship name
_aarColumnMapping :: HashMap (Column b) (Column b), -- Column of left table to join with _aarColumnMapping :: HashMap (ColumnPath b) (ColumnPath b), -- Column of left table to join with
_aarNullable :: Nullable, -- is the target object allowed to be missing? _aarNullable :: Nullable, -- is the target object allowed to be missing?
_aarAnnSelect :: a -- Current table. Almost ~ to SQL Select _aarAnnSelect :: a -- Current table. Almost ~ to SQL Select
} }

View File

@ -40,6 +40,7 @@ import Hasura.RQL.Types.Session (SessionVariables)
import Hasura.RQL.Types.SourceConfiguration import Hasura.RQL.Types.SourceConfiguration
import Hasura.SQL.Types import Hasura.SQL.Types
import Language.GraphQL.Draft.Syntax qualified as G import Language.GraphQL.Draft.Syntax qualified as G
import Witch (From)
type SessionVarType b = CollectableType (ScalarType b) type SessionVarType b = CollectableType (ScalarType b)
@ -81,6 +82,7 @@ class
( HasSourceConfiguration b, ( HasSourceConfiguration b,
Representable (BasicOrderType b), Representable (BasicOrderType b),
Representable (Column b), Representable (Column b),
Representable (ColumnPath b),
Representable (ComputedFieldDefinition b), Representable (ComputedFieldDefinition b),
Representable (ComputedFieldImplicitArguments b), Representable (ComputedFieldImplicitArguments b),
Representable (ComputedFieldReturn b), Representable (ComputedFieldReturn b),
@ -104,14 +106,18 @@ class
Ord (FunctionName b), Ord (FunctionName b),
Ord (ScalarType b), Ord (ScalarType b),
Ord (Column b), Ord (Column b),
Ord (ColumnPath b),
Ord (ComputedFieldReturn b), Ord (ComputedFieldReturn b),
Ord (ComputedFieldImplicitArguments b), Ord (ComputedFieldImplicitArguments b),
Ord (ConstraintName b), Ord (ConstraintName b),
Ord (FunctionArgument b), Ord (FunctionArgument b),
Ord (XComputedField b), Ord (XComputedField b),
Data (TableName b), Data (TableName b),
From (Column b) (ColumnPath b),
FromJSON (BackendConfig b), FromJSON (BackendConfig b),
FromJSON (Column b), FromJSON (Column b),
FromJSON (ColumnPath b),
FromJSON (ColumnPath b),
FromJSON (ComputedFieldDefinition b), FromJSON (ComputedFieldDefinition b),
FromJSON (ConnectionTemplateRequestContext b), FromJSON (ConnectionTemplateRequestContext b),
FromJSON (ConstraintName b), FromJSON (ConstraintName b),
@ -123,17 +129,22 @@ class
FromJSON (ScalarType b), FromJSON (ScalarType b),
FromJSON (TableName b), FromJSON (TableName b),
FromJSONKey (Column b), FromJSONKey (Column b),
FromJSONKey (ColumnPath b),
FromJSONKey (ConstraintName b), FromJSONKey (ConstraintName b),
HasCodec (BackendConfig b), HasCodec (BackendConfig b),
HasCodec (BackendSourceKind b), HasCodec (BackendSourceKind b),
HasCodec (Column b), HasCodec (Column b),
HasCodec (ColumnPath b),
HasCodec (ComputedFieldDefinition b), HasCodec (ComputedFieldDefinition b),
HasCodec (FunctionName b), HasCodec (FunctionName b),
HasCodec (FunctionReturnType b), HasCodec (FunctionReturnType b),
HasCodec (ScalarType b), HasCodec (ScalarType b),
HasCodec (TableName b), HasCodec (TableName b),
Hashable (Column b),
Hashable (ColumnPath b),
ToJSON (BackendConfig b), ToJSON (BackendConfig b),
ToJSON (Column b), ToJSON (Column b),
ToJSON (ColumnPath b),
ToJSON (ConstraintName b), ToJSON (ConstraintName b),
ToJSON (ExecutionStatistics b), ToJSON (ExecutionStatistics b),
ToJSON (FunctionArgument b), ToJSON (FunctionArgument b),
@ -150,6 +161,7 @@ class
ToJSON (HealthCheckTest b), ToJSON (HealthCheckTest b),
ToJSON (ResolvedConnectionTemplate b), ToJSON (ResolvedConnectionTemplate b),
ToJSONKey (Column b), ToJSONKey (Column b),
ToJSONKey (ColumnPath b),
ToJSONKey (ConstraintName b), ToJSONKey (ConstraintName b),
ToJSONKey (ScalarType b), ToJSONKey (ScalarType b),
ToTxt (Column b), ToTxt (Column b),
@ -160,6 +172,7 @@ class
ToErrorValue (Column b), ToErrorValue (Column b),
ToErrorValue (TableName b), ToErrorValue (TableName b),
Typeable (Column b), Typeable (Column b),
Typeable (ColumnPath b),
Typeable b, Typeable b,
HasTag b, HasTag b,
Traversable (CountType b), Traversable (CountType b),
@ -232,6 +245,9 @@ class
-- Name of a 'column' -- Name of a 'column'
type Column b :: Type type Column b :: Type
-- Path to a column
type ColumnPath b :: Type
type ScalarValue b :: Type type ScalarValue b :: Type
type ScalarType b :: Type type ScalarType b :: Type
@ -443,6 +459,14 @@ class
(Column b, [RemoteRelSupportedOp RemoteRelSessionVariableORLiteralValue]) -> (Column b, [RemoteRelSupportedOp RemoteRelSessionVariableORLiteralValue]) ->
m [Text] m [Text]
-- | Get the top-level column from a ColumnPath
-- For backends that don't support nested objects (i.e. where ColumnPath b = Column b) this will be `id`.
getColumnPathColumn :: ColumnPath b -> Column b
-- | Convert a singleton ColumnPath to a Column
-- Should return Nothing for paths to nested fields
tryColumnPathToColumn :: ColumnPath b -> Maybe (Column b)
backendSupportsNestedObjects :: Either QErr (XNestedObjects b) backendSupportsNestedObjects :: Either QErr (XNestedObjects b)
default backendSupportsNestedObjects :: (XNestedObjects b ~ XDisable) => Either QErr (XNestedObjects b) default backendSupportsNestedObjects :: (XNestedObjects b ~ XDisable) => Either QErr (XNestedObjects b)
backendSupportsNestedObjects = throw400 InvalidConfiguration "Nested objects not supported" backendSupportsNestedObjects = throw400 InvalidConfiguration "Nested objects not supported"

View File

@ -10,6 +10,7 @@ module Hasura.RQL.Types.Relationships.Local
ObjRelUsingChoice (..), ObjRelUsingChoice (..),
RelDef (..), RelDef (..),
RelTarget (..), RelTarget (..),
RelMapping (..),
RelInfo (..), RelInfo (..),
RelManualConfig (..), RelManualConfig (..),
RelManualTableConfig (..), RelManualTableConfig (..),
@ -31,6 +32,8 @@ import Autodocodec.Extended (optionalFieldOrIncludedNull', typeableName)
import Control.Lens (makeLenses) import Control.Lens (makeLenses)
import Data.Aeson.KeyMap qualified as KM import Data.Aeson.KeyMap qualified as KM
import Data.Aeson.Types import Data.Aeson.Types
import Data.Bitraversable
import Data.HashMap.Strict qualified as HashMap
import Data.Text qualified as T import Data.Text qualified as T
import Data.Typeable (Typeable) import Data.Typeable (Typeable)
import Hasura.NativeQuery.Types (NativeQueryName) import Hasura.NativeQuery.Types (NativeQueryName)
@ -39,6 +42,7 @@ import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendTag (backendPrefix) import Hasura.RQL.Types.BackendTag (backendPrefix)
import Hasura.RQL.Types.BackendType import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Common import Hasura.RQL.Types.Common
import Witch qualified
data RelDef a = RelDef data RelDef a = RelDef
{ _rdName :: RelName, { _rdName :: RelName,
@ -112,7 +116,7 @@ deriving instance (Backend b) => Eq (RelManualNativeQueryConfig b)
deriving instance (Backend b) => Show (RelManualNativeQueryConfig b) deriving instance (Backend b) => Show (RelManualNativeQueryConfig b)
data RelManualCommon (b :: BackendType) = RelManualCommon data RelManualCommon (b :: BackendType) = RelManualCommon
{ rmColumns :: HashMap (Column b) (Column b), { rmColumns :: RelMapping b,
rmInsertOrder :: Maybe InsertOrder rmInsertOrder :: Maybe InsertOrder
} }
deriving (Generic) deriving (Generic)
@ -188,7 +192,7 @@ instance (FromJSON a, Backend b) => FromJSON (RelUsing b a) where
data ArrRelUsingFKeyOn (b :: BackendType) = ArrRelUsingFKeyOn data ArrRelUsingFKeyOn (b :: BackendType) = ArrRelUsingFKeyOn
{ arufTable :: TableName b, { arufTable :: TableName b,
arufColumns :: NonEmpty (Column b) arufColumns :: NonEmpty (ColumnPath b)
} }
deriving (Generic) deriving (Generic)
@ -224,8 +228,8 @@ instance (ToAesonPairs a, Backend b) => ToJSON (WithTable b a) where
object $ ("source" .= sourceName) : ("table" .= tn) : toAesonPairs rel object $ ("source" .= sourceName) : ("table" .= tn) : toAesonPairs rel
data ObjRelUsingChoice b data ObjRelUsingChoice b
= SameTable (NonEmpty (Column b)) = SameTable (NonEmpty (ColumnPath b))
| RemoteTable (TableName b) (NonEmpty (Column b)) | RemoteTable (TableName b) (NonEmpty (ColumnPath b))
deriving (Generic) deriving (Generic)
deriving instance (Backend b) => Eq (ObjRelUsingChoice b) deriving instance (Backend b) => Eq (ObjRelUsingChoice b)
@ -235,10 +239,10 @@ deriving instance (Backend b) => Show (ObjRelUsingChoice b)
instance (Backend b) => HasCodec (ObjRelUsingChoice b) where instance (Backend b) => HasCodec (ObjRelUsingChoice b) where
codec = dimapCodec dec enc $ disjointEitherCodec sameTableCodec remoteTableCodec codec = dimapCodec dec enc $ disjointEitherCodec sameTableCodec remoteTableCodec
where where
sameTableCodec :: AC.JSONCodec (Either (Column b) (NonEmpty (Column b))) sameTableCodec :: AC.JSONCodec (Either (ColumnPath b) (NonEmpty (ColumnPath b)))
sameTableCodec = disjointEitherCodec codec codec sameTableCodec = disjointEitherCodec codec codec
remoteTableCodec :: AC.JSONCodec (Either (TableName b, Column b) (TableName b, NonEmpty (Column b))) remoteTableCodec :: AC.JSONCodec (Either (TableName b, ColumnPath b) (TableName b, NonEmpty (ColumnPath b)))
remoteTableCodec = remoteTableCodec =
singleOrMultipleRelColumnsCodec @b singleOrMultipleRelColumnsCodec @b
$ backendPrefix @b $ backendPrefix @b
@ -262,8 +266,8 @@ singleOrMultipleRelColumnsCodec ::
Text -> Text ->
AC.JSONCodec AC.JSONCodec
( Either ( Either
(TableName b, Column b) (TableName b, ColumnPath b)
(TableName b, NonEmpty (Column b)) (TableName b, NonEmpty (ColumnPath b))
) )
singleOrMultipleRelColumnsCodec codecName = singleOrMultipleRelColumnsCodec codecName =
disjointEitherCodec disjointEitherCodec
@ -310,7 +314,7 @@ instance (Backend b) => FromJSON (ObjRelUsingChoice b) where
pure $ RemoteTable table cols pure $ RemoteTable table cols
val -> SameTable <$> parseColumns val val -> SameTable <$> parseColumns val
where where
parseColumns :: Value -> Parser (NonEmpty (Column b)) parseColumns :: Value -> Parser (NonEmpty (ColumnPath b))
parseColumns = \case parseColumns = \case
v@(String _) -> pure <$> parseJSON v v@(String _) -> pure <$> parseJSON v
v@(Array _) -> parseJSON v v@(Array _) -> parseJSON v
@ -321,12 +325,12 @@ instance (Backend b) => HasCodec (ArrRelUsingFKeyOn b) where
dimapCodec dec enc dimapCodec dec enc
$ singleOrMultipleRelColumnsCodec @b (backendPrefix @b <> "ArrRelUsingFKeyOn") $ singleOrMultipleRelColumnsCodec @b (backendPrefix @b <> "ArrRelUsingFKeyOn")
where where
dec :: (Either (TableName b, Column b) (TableName b, NonEmpty (Column b))) -> ArrRelUsingFKeyOn b dec :: (Either (TableName b, ColumnPath b) (TableName b, NonEmpty (ColumnPath b))) -> ArrRelUsingFKeyOn b
dec = \case dec = \case
Left (qt, col) -> ArrRelUsingFKeyOn qt (pure col) Left (qt, col) -> ArrRelUsingFKeyOn qt (pure col)
Right (qt, cols) -> ArrRelUsingFKeyOn qt cols Right (qt, cols) -> ArrRelUsingFKeyOn qt cols
enc :: ArrRelUsingFKeyOn b -> (Either (TableName b, Column b) (TableName b, NonEmpty (Column b))) enc :: ArrRelUsingFKeyOn b -> (Either (TableName b, ColumnPath b) (TableName b, NonEmpty (ColumnPath b)))
enc = \case enc = \case
ArrRelUsingFKeyOn qt (col :| []) -> Left (qt, col) ArrRelUsingFKeyOn qt (col :| []) -> Left (qt, col)
ArrRelUsingFKeyOn qt cols -> Right (qt, cols) ArrRelUsingFKeyOn qt cols -> Right (qt, cols)
@ -352,7 +356,7 @@ instance (Backend b) => FromJSON (ArrRelUsingFKeyOn b) where
pure $ ArrRelUsingFKeyOn table cols pure $ ArrRelUsingFKeyOn table cols
_ -> fail "Expecting object { table, columns }." _ -> fail "Expecting object { table, columns }."
where where
parseColumns :: Value -> Parser (NonEmpty (Column b)) parseColumns :: Value -> Parser (NonEmpty (ColumnPath b))
parseColumns = \case parseColumns = \case
v@(String _) -> pure <$> parseJSON v v@(String _) -> pure <$> parseJSON v
v@(Array _) -> parseJSON v v@(Array _) -> parseJSON v
@ -391,10 +395,48 @@ instance (Backend b) => ToJSON (RelTarget b) where
--- ---
newtype RelMapping (b :: BackendType) = RelMapping {unRelMapping :: HashMap (ColumnPath b) (ColumnPath b)}
deriving (Generic)
deriving instance (Backend b) => Show (RelMapping b)
deriving instance (Backend b) => Eq (RelMapping b)
deriving instance (Backend b) => Ord (RelMapping b)
deriving via AC.Autodocodec (RelMapping b) instance (Backend b) => FromJSON (RelMapping b)
deriving via AC.Autodocodec (RelMapping b) instance (Backend b) => ToJSON (RelMapping b)
instance (Backend b) => NFData (RelMapping b)
instance (Backend b) => Hashable (RelMapping b)
-- If all keys in the RelMapping have a singleton ColumnPath then we want to
-- want to represent the mapping as a JSON object with the source columns as properties
-- (using `codec @(HashMap (Column b) (ColumnPath b))`).
-- This is required for metadata and API backwards compatibilty.
-- If some of the keys are not singletons then we can't use a JSON object so we use
-- an array of pairs instead, as provided by `codec @(HashMap (ColumnPath b) (ColumnPath b))`
instance (Backend b) => HasCodec (RelMapping b) where
codec =
AC.matchChoiceCodec
(AC.dimapCodec RelMapping unRelMapping $ codec @(HashMap (ColumnPath b) (ColumnPath b)))
(AC.dimapCodec toRelMapping id $ codec @(HashMap (Column b) (ColumnPath b)))
\m -> maybeToEither m (tryFromRelMapping m)
where
toRelMapping :: HashMap (Column b) (ColumnPath b) -> RelMapping b
toRelMapping = RelMapping . HashMap.mapKeys Witch.from
tryFromRelMapping :: RelMapping b -> Maybe (HashMap (Column b) (ColumnPath b))
tryFromRelMapping = fmap HashMap.fromList . traverse (bitraverse (tryColumnPathToColumn @b) pure) . HashMap.toList . unRelMapping
---
data RelInfo (b :: BackendType) = RelInfo data RelInfo (b :: BackendType) = RelInfo
{ riName :: RelName, { riName :: RelName,
riType :: RelType, riType :: RelType,
riMapping :: HashMap (Column b) (Column b), riMapping :: RelMapping b,
riTarget :: RelTarget b, riTarget :: RelTarget b,
riIsManual :: Bool, riIsManual :: Bool,
riInsertOrder :: InsertOrder riInsertOrder :: InsertOrder

View File

@ -38,6 +38,7 @@ import Data.Text (Text)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Hasura.LogicalModel.Metadata import Hasura.LogicalModel.Metadata
import Hasura.RQL.Types.Backend (Backend (..), ConstraintName) import Hasura.RQL.Types.Backend (Backend (..), ConstraintName)
import Hasura.RQL.Types.Relationships.Local (RelMapping (..))
import Hasura.RQL.Types.Source.Column (SourceColumnInfo) import Hasura.RQL.Types.Source.Column (SourceColumnInfo)
import Hasura.RQL.Types.Source.TableType import Hasura.RQL.Types.Source.TableType
import Prelude import Prelude
@ -102,7 +103,7 @@ instance (Backend b) => HasCodec (SourceForeignKeys b) where
data SourceConstraint b = SourceConstraint data SourceConstraint b = SourceConstraint
{ _scForeignTable :: TableName b, { _scForeignTable :: TableName b,
_scColumnMapping :: HashMap (Column b) (Column b) _scColumnMapping :: RelMapping b
} }
deriving stock (Generic) deriving stock (Generic)
deriving anyclass (Hashable) deriving anyclass (Hashable)

View File

@ -984,7 +984,7 @@ instance (Backend b) => FromJSON (UniqueConstraint b) where
data ForeignKey (b :: BackendType) = ForeignKey data ForeignKey (b :: BackendType) = ForeignKey
{ _fkConstraint :: Constraint b, { _fkConstraint :: Constraint b,
_fkForeignTable :: TableName b, _fkForeignTable :: TableName b,
_fkColumnMapping :: NEHashMap (Column b) (Column b) _fkColumnMapping :: NEHashMap (ColumnPath b) (ColumnPath b)
} }
deriving (Generic) deriving (Generic)

View File

@ -1,7 +1,7 @@
{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE QuasiQuotes #-}
module Hasura.Backends.DataConnector.API.V0.ColumnSpec (spec, genColumnName, genColumnType, genColumnInfo, genColumnValueGenerationStrategy) where module Hasura.Backends.DataConnector.API.V0.ColumnSpec (spec, genColumnName, genColumnSelector, genColumnType, genColumnInfo, genColumnValueGenerationStrategy) where
import Data.Aeson.QQ.Simple (aesonQQ) import Data.Aeson.QQ.Simple (aesonQQ)
import Hasura.Backends.DataConnector.API.V0 import Hasura.Backends.DataConnector.API.V0
@ -19,6 +19,12 @@ spec = do
describe "ColumnName" $ do describe "ColumnName" $ do
testToFromJSONToSchema (ColumnName "my_column_name") [aesonQQ|"my_column_name"|] testToFromJSONToSchema (ColumnName "my_column_name") [aesonQQ|"my_column_name"|]
jsonOpenApiProperties genColumnName jsonOpenApiProperties genColumnName
describe "ColumnSelector" $ do
describe "single column selector"
$ testToFromJSONToSchema (ColumnSelectorColumn $ ColumnName "foo") [aesonQQ|"foo"|]
describe "nested path selector"
$ testToFromJSONToSchema (ColumnSelectorPath [ColumnName "foo", ColumnName "bar"]) [aesonQQ|["foo","bar"]|]
jsonOpenApiProperties genColumnSelector
describe "ColumnInfo" $ do describe "ColumnInfo" $ do
describe "minimal" describe "minimal"
$ testFromJSON $ testFromJSON
@ -56,6 +62,13 @@ spec = do
genColumnName :: (MonadGen m) => m ColumnName genColumnName :: (MonadGen m) => m ColumnName
genColumnName = ColumnName <$> genArbitraryAlphaNumText defaultRange genColumnName = ColumnName <$> genArbitraryAlphaNumText defaultRange
genColumnSelector :: (MonadGen m) => m ColumnSelector
genColumnSelector =
Gen.choice
[ ColumnSelectorPath <$> Gen.nonEmpty defaultRange genColumnName,
ColumnSelectorColumn <$> genColumnName
]
genColumnType :: Gen ColumnType genColumnType :: Gen ColumnType
genColumnType = genColumnType =
Gen.choice Gen.choice

View File

@ -10,14 +10,13 @@ module Hasura.Backends.DataConnector.API.V0.ExpressionSpec
genExpression, genExpression,
genRedactionExpressionName, genRedactionExpressionName,
genTargetRedactionExpressions, genTargetRedactionExpressions,
genColumnSelector,
) )
where where
import Data.Aeson import Data.Aeson
import Data.Aeson.QQ.Simple (aesonQQ) import Data.Aeson.QQ.Simple (aesonQQ)
import Hasura.Backends.DataConnector.API.V0 import Hasura.Backends.DataConnector.API.V0
import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnName) import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnSelector)
import Hasura.Backends.DataConnector.API.V0.RelationshipsSpec (genRelationshipName) import Hasura.Backends.DataConnector.API.V0.RelationshipsSpec (genRelationshipName)
import Hasura.Backends.DataConnector.API.V0.ScalarSpec (genScalarType, genScalarValue) import Hasura.Backends.DataConnector.API.V0.ScalarSpec (genScalarType, genScalarValue)
import Hasura.Backends.DataConnector.API.V0.TableSpec (genTableName) import Hasura.Backends.DataConnector.API.V0.TableSpec (genTableName)
@ -84,13 +83,6 @@ spec = do
$ testToFromJSONToSchema CurrentTable [aesonQQ|[]|] $ testToFromJSONToSchema CurrentTable [aesonQQ|[]|]
jsonOpenApiProperties genColumnPath jsonOpenApiProperties genColumnPath
describe "ColumnSelector" $ do
describe "single column selector"
$ testToFromJSONToSchema (ColumnSelector [ColumnName "foo"]) [aesonQQ|"foo"|]
describe "nested path selector"
$ testToFromJSONToSchema (ColumnSelector [ColumnName "foo", ColumnName "bar"]) [aesonQQ|["foo","bar"]|]
jsonOpenApiProperties genColumnSelector
describe "ComparisonValue" $ do describe "ComparisonValue" $ do
describe "AnotherColumnComparison" describe "AnotherColumnComparison"
$ testToFromJSONToSchema $ testToFromJSONToSchema
@ -290,10 +282,6 @@ genColumnPath :: (MonadGen m) => m ColumnPath
genColumnPath = genColumnPath =
Gen.element [CurrentTable, QueryTable] Gen.element [CurrentTable, QueryTable]
genColumnSelector :: (MonadGen m) => m ColumnSelector
genColumnSelector =
ColumnSelector <$> Gen.nonEmpty defaultRange genColumnName
genComparisonValue :: (MonadGen m, GenBase m ~ Identity) => m ComparisonValue genComparisonValue :: (MonadGen m, GenBase m ~ Identity) => m ComparisonValue
genComparisonValue = genComparisonValue =
Gen.choice Gen.choice

View File

@ -12,7 +12,8 @@ import Data.Aeson.QQ.Simple (aesonQQ)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Hasura.Backends.DataConnector.API.V0 import Hasura.Backends.DataConnector.API.V0
import Hasura.Backends.DataConnector.API.V0.AggregateSpec (genSingleColumnAggregate) import Hasura.Backends.DataConnector.API.V0.AggregateSpec (genSingleColumnAggregate)
import Hasura.Backends.DataConnector.API.V0.ExpressionSpec (genColumnSelector, genExpression, genRedactionExpressionName) import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnSelector)
import Hasura.Backends.DataConnector.API.V0.ExpressionSpec (genExpression, genRedactionExpressionName)
import Hasura.Backends.DataConnector.API.V0.RelationshipsSpec (genRelationshipName) import Hasura.Backends.DataConnector.API.V0.RelationshipsSpec (genRelationshipName)
import Hasura.Generator.Common (defaultRange) import Hasura.Generator.Common (defaultRange)
import Hasura.Prelude import Hasura.Prelude

View File

@ -12,7 +12,7 @@ where
import Data.Aeson.QQ.Simple (aesonQQ) import Data.Aeson.QQ.Simple (aesonQQ)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Hasura.Backends.DataConnector.API.V0 import Hasura.Backends.DataConnector.API.V0
import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnName) import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnSelector)
import Hasura.Backends.DataConnector.API.V0.TableSpec (genTableName, genTableTarget) import Hasura.Backends.DataConnector.API.V0.TableSpec (genTableName, genTableTarget)
import Hasura.Generator.Common (defaultRange, genArbitraryAlphaNumText) import Hasura.Generator.Common (defaultRange, genArbitraryAlphaNumText)
import Hasura.Prelude import Hasura.Prelude
@ -38,7 +38,7 @@ spec = do
Relationship Relationship
{ _rTarget = TTable (TargetTable (TableName ["target_table_name"])), { _rTarget = TTable (TargetTable (TableName ["target_table_name"])),
_rRelationshipType = ObjectRelationship, _rRelationshipType = ObjectRelationship,
_rColumnMapping = [(ColumnName "outer_column", ColumnName "inner_column")] _rColumnMapping = ColumnPathMapping [(mkColumnSelector $ ColumnName "outer_column", mkColumnSelector $ ColumnName "inner_column")]
} }
testToFromJSONToSchema testToFromJSONToSchema
relationship relationship
@ -51,18 +51,20 @@ spec = do
} }
|] |]
jsonOpenApiProperties genRelationship jsonOpenApiProperties genRelationship
describe "ColumnPathMapping"
$ jsonOpenApiProperties genColumnPathMapping
describe "TableRelationships" $ do describe "TableRelationships" $ do
let relationshipA = let relationshipA =
Relationship Relationship
{ _rTarget = TTable (TargetTable (TableName ["target_table_name_a"])), { _rTarget = TTable (TargetTable (TableName ["target_table_name_a"])),
_rRelationshipType = ObjectRelationship, _rRelationshipType = ObjectRelationship,
_rColumnMapping = [(ColumnName "outer_column_a", ColumnName "inner_column_a")] _rColumnMapping = ColumnPathMapping [(mkColumnSelector $ ColumnName "outer_column_a", mkColumnSelector $ ColumnName "inner_column_a")]
} }
let relationshipB = let relationshipB =
Relationship Relationship
{ _rTarget = TTable (TargetTable (TableName ["target_table_name_b"])), { _rTarget = TTable (TargetTable (TableName ["target_table_name_b"])),
_rRelationshipType = ArrayRelationship, _rRelationshipType = ArrayRelationship,
_rColumnMapping = [(ColumnName "outer_column_b", ColumnName "inner_column_b")] _rColumnMapping = ColumnPathMapping [(mkColumnSelector $ ColumnName "outer_column_b", mkColumnSelector $ ColumnName "inner_column_b")]
} }
let tableRelationships = let tableRelationships =
TableRelationships TableRelationships
@ -109,7 +111,7 @@ genRelationship =
Relationship Relationship
<$> genTableTarget <$> genTableTarget
<*> genRelationshipType <*> genRelationshipType
<*> (HashMap.fromList <$> Gen.list defaultRange ((,) <$> genColumnName <*> genColumnName)) <*> genColumnPathMapping
genRelationships :: Gen Relationships genRelationships :: Gen Relationships
genRelationships = (RTable <$> genTableRelationships) <|> (RFunction <$> genFunctionRelationships) genRelationships = (RTable <$> genTableRelationships) <|> (RFunction <$> genFunctionRelationships)
@ -128,3 +130,6 @@ genFunctionRelationships =
genFunctionName :: (MonadGen m) => m FunctionName genFunctionName :: (MonadGen m) => m FunctionName
genFunctionName = FunctionName <$> Gen.nonEmpty (linear 1 3) (genArbitraryAlphaNumText defaultRange) genFunctionName = FunctionName <$> Gen.nonEmpty (linear 1 3) (genArbitraryAlphaNumText defaultRange)
genColumnPathMapping :: (MonadGen m) => m ColumnPathMapping
genColumnPathMapping = ColumnPathMapping . HashMap.fromList <$> Gen.list defaultRange ((,) <$> genColumnSelector <*> genColumnSelector)

View File

@ -6,7 +6,7 @@ module Hasura.Backends.DataConnector.API.V0.TableSpec (spec, genTableName, genTa
import Data.Aeson.QQ.Simple (aesonQQ) import Data.Aeson.QQ.Simple (aesonQQ)
import Data.HashMap.Strict qualified as HashMap import Data.HashMap.Strict qualified as HashMap
import Hasura.Backends.DataConnector.API.V0 import Hasura.Backends.DataConnector.API.V0
import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnInfo, genColumnName) import Hasura.Backends.DataConnector.API.V0.ColumnSpec (genColumnInfo, genColumnName, genColumnSelector)
import Hasura.Generator.Common import Hasura.Generator.Common
import Hasura.Prelude import Hasura.Prelude
import Hedgehog import Hedgehog
@ -60,7 +60,14 @@ spec = do
Table Table
[ColumnInfo (ColumnName "id") (ColumnTypeScalar $ ScalarType "string") False Nothing False False Nothing] [ColumnInfo (ColumnName "id") (ColumnTypeScalar $ ScalarType "string") False Nothing False False Nothing]
(Just $ ColumnName "id" :| []) (Just $ ColumnName "id" :| [])
(ForeignKeys $ HashMap.singleton (ConstraintName "Artist") (Constraint (TableName ["artist_table"]) (HashMap.singleton (ColumnName "ArtistId") (ColumnName "ArtistId")))) ( ForeignKeys
$ HashMap.singleton
(ConstraintName "Artist")
( Constraint
(TableName ["artist_table"])
(ColumnPathMapping $ HashMap.singleton (mkColumnSelector $ ColumnName "ArtistId") (mkColumnSelector $ ColumnName "ArtistId"))
)
)
(Just "my description") (Just "my description")
False False
False False
@ -101,7 +108,7 @@ genConstraintName = ConstraintName <$> genArbitraryAlphaNumText defaultRange
genConstraint :: (MonadGen m) => m Constraint genConstraint :: (MonadGen m) => m Constraint
genConstraint = genConstraint =
let mapping = genHashMap genColumnName genColumnName defaultRange let mapping = ColumnPathMapping <$> genHashMap genColumnSelector genColumnSelector defaultRange
in Constraint <$> genTableName <*> mapping in Constraint <$> genTableName <*> mapping
genTableType :: (MonadGen m) => m TableType genTableType :: (MonadGen m) => m TableType

View File

@ -47,6 +47,7 @@ genSelectArgsG genA = do
Gen.maybe Gen.maybe
$ genAnnBoolExp $ genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn
genColumn genColumn
genTableName genTableName
genScalarType genScalarType
@ -66,6 +67,7 @@ genSelectArgsG genA = do
genBasicOrderType genBasicOrderType
genNullsOrderType genNullsOrderType
( genAnnotatedOrderByElement @_ @('Postgres 'Vanilla) ( genAnnotatedOrderByElement @_ @('Postgres 'Vanilla)
genColumn
genColumn genColumn
genTableName genTableName
genScalarType genScalarType
@ -89,6 +91,7 @@ genSelectArgsG genA = do
$ AnnDistinctColumn $ AnnDistinctColumn
<$> genColumn <$> genColumn
<*> genAnnRedactionExp <*> genAnnRedactionExp
genColumn
genColumn genColumn
genTableName genTableName
genScalarType genScalarType

View File

@ -24,7 +24,7 @@ import Hedgehog.Gen qualified as Gen
genTablePermG :: (MonadGen m) => m a -> m (TablePermG ('Postgres 'Vanilla) a) genTablePermG :: (MonadGen m) => m a -> m (TablePermG ('Postgres 'Vanilla) a)
genTablePermG genA = do genTablePermG genA = do
let genV = genAnnBoolExpFld @_ @('Postgres 'Vanilla) genColumn genTableName genScalarType genFunctionName genXComputedField (genBooleanOperators genA) (genFunctionArgumentExp genA) genA let genV = genAnnBoolExpFld @_ @('Postgres 'Vanilla) genColumn genColumn genTableName genScalarType genFunctionName genXComputedField (genBooleanOperators genA) (genFunctionArgumentExp genA) genA
gBoolExp <- genAnnBoolExp @_ @_ @('Postgres 'Vanilla) genV genTableName gBoolExp <- genAnnBoolExp @_ @_ @('Postgres 'Vanilla) genV genTableName
limit <- Gen.maybe (Gen.integral defaultRange) limit <- Gen.maybe (Gen.integral defaultRange)
pure $ TablePerm gBoolExp limit pure $ TablePerm gBoolExp limit

View File

@ -29,7 +29,7 @@ import Hasura.RQL.Types.BackendType (BackendSourceKind (PostgresVanillaKind), Ba
import Hasura.RQL.Types.Column (ColumnType (ColumnScalar), ColumnValue (..)) import Hasura.RQL.Types.Column (ColumnType (ColumnScalar), ColumnValue (..))
import Hasura.RQL.Types.Common (InsertOrder (..), RelName (..), RelType (..), SourceName (..)) import Hasura.RQL.Types.Common (InsertOrder (..), RelName (..), RelType (..), SourceName (..))
import Hasura.RQL.Types.NamingCase (NamingCase (..)) import Hasura.RQL.Types.NamingCase (NamingCase (..))
import Hasura.RQL.Types.Relationships.Local (RelInfo (..), RelTarget (..)) import Hasura.RQL.Types.Relationships.Local (RelInfo (..), RelMapping (..), RelTarget (..))
import Hasura.RQL.Types.Schema.Options qualified as Options import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.RQL.Types.Source (DBObjectsIntrospection (..), SourceInfo (..)) import Hasura.RQL.Types.Source (DBObjectsIntrospection (..), SourceInfo (..))
import Hasura.RQL.Types.SourceCustomization (ResolvedSourceCustomization (..)) import Hasura.RQL.Types.SourceCustomization (ResolvedSourceCustomization (..))
@ -307,7 +307,7 @@ spec = do
RelInfo RelInfo
{ riName = RelName [nonEmptyTextQQ|tracks|], { riName = RelName [nonEmptyTextQQ|tracks|],
riType = ArrRel, riType = ArrRel,
riMapping = HashMap.fromList [("id", "album_id")], riMapping = RelMapping $ HashMap.fromList [("id", "album_id")],
riTarget = RelTargetTable (mkTable "track"), riTarget = RelTargetTable (mkTable "track"),
riIsManual = False, riIsManual = False,
riInsertOrder = AfterParent riInsertOrder = AfterParent

View File

@ -62,7 +62,9 @@ genAnnRedactionExp ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (TableName b) -> m (TableName b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -73,6 +75,7 @@ genAnnRedactionExp ::
m (AnnRedactionExp b a) m (AnnRedactionExp b a)
genAnnRedactionExp genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -87,6 +90,7 @@ genAnnRedactionExp
<$> genAnnBoolExp <$> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -129,7 +133,9 @@ genAnnBoolExpFld ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (TableName b) -> m (TableName b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -140,6 +146,7 @@ genAnnBoolExpFld ::
m (AnnBoolExpFld b a) m (AnnBoolExpFld b a)
genAnnBoolExpFld genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -157,6 +164,7 @@ genAnnBoolExpFld
genScalarType genScalarType
<*> genAnnRedactionExp <*> genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -175,11 +183,12 @@ genAnnBoolExpFld
) )
relationship = relationship =
AVRelationship AVRelationship
<$> genRelInfo genTableName genColumn <$> genRelInfo genTableName genColumnPath
<*> ( RelationshipFilters <*> ( RelationshipFilters
<$> genAnnBoolExp <$> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -192,6 +201,7 @@ genAnnBoolExpFld
<*> genAnnBoolExp <*> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -207,6 +217,7 @@ genAnnBoolExpFld
<$> genAnnComputedFieldBolExp <$> genAnnComputedFieldBolExp
genTableName genTableName
genColumn genColumn
genColumnPath
genScalarType genScalarType
genBooleanOperators genBooleanOperators
genXComputedField genXComputedField
@ -216,15 +227,15 @@ genAnnBoolExpFld
genRelInfo :: genRelInfo ::
(MonadGen m) => (MonadGen m) =>
(Hashable (Column b)) => (Hashable (ColumnPath b)) =>
m (TableName b) -> m (TableName b) ->
m (Column b) -> m (ColumnPath b) ->
m (RelInfo b) m (RelInfo b)
genRelInfo genTableName genColumn = genRelInfo genTableName genColumn =
RelInfo RelInfo
<$> genRelName <$> genRelName
<*> genRelType <*> genRelType
<*> genHashMap genColumn genColumn defaultRange <*> (RelMapping <$> genHashMap genColumn genColumn defaultRange)
<*> genRelTarget genTableName <*> genRelTarget genTableName
<*> bool_ <*> bool_
<*> genInsertOrder <*> genInsertOrder
@ -252,8 +263,10 @@ genAnnComputedFieldBolExp ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (TableName b) -> m (TableName b) ->
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (BooleanOperators b a) -> m (BooleanOperators b a) ->
m (XComputedField b) -> m (XComputedField b) ->
@ -264,6 +277,7 @@ genAnnComputedFieldBolExp ::
genAnnComputedFieldBolExp genAnnComputedFieldBolExp
genTableName genTableName
genColumn genColumn
genColumnPath
genScalarType genScalarType
genBooleanOperators genBooleanOperators
genXComputedField genXComputedField
@ -278,6 +292,7 @@ genAnnComputedFieldBolExp
<*> genComputedFieldBoolExp <*> genComputedFieldBoolExp
genTableName genTableName
genColumn genColumn
genColumnPath
genScalarType genScalarType
genFunctionName genFunctionName
genXComputedField genXComputedField
@ -289,8 +304,10 @@ genComputedFieldBoolExp ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (TableName b) -> m (TableName b) ->
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (FunctionName b) -> m (FunctionName b) ->
m (XComputedField b) -> m (XComputedField b) ->
@ -301,6 +318,7 @@ genComputedFieldBoolExp ::
genComputedFieldBoolExp genComputedFieldBoolExp
genTableName genTableName
genColumn genColumn
genColumnPath
genScalarType genScalarType
genFunctionName genFunctionName
genXComputedField genXComputedField
@ -311,6 +329,7 @@ genComputedFieldBoolExp
[ CFBEScalar [ CFBEScalar
<$> genAnnRedactionExp <$> genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -332,6 +351,7 @@ genComputedFieldBoolExp
<*> genAnnBoolExp <*> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -492,7 +512,9 @@ genAnnotatedOrderByElement ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (TableName b) -> m (TableName b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -503,6 +525,7 @@ genAnnotatedOrderByElement ::
m (AnnotatedOrderByElement b a) m (AnnotatedOrderByElement b a)
genAnnotatedOrderByElement genAnnotatedOrderByElement
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -525,6 +548,7 @@ genAnnotatedOrderByElement
genScalarType genScalarType
<*> genAnnRedactionExp <*> genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -534,10 +558,11 @@ genAnnotatedOrderByElement
genA genA
objectRelation = objectRelation =
AOCObjectRelation AOCObjectRelation
<$> genRelInfo genTableName genColumn <$> genRelInfo genTableName genColumnPath
<*> genAnnBoolExp <*> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -549,6 +574,7 @@ genAnnotatedOrderByElement
genTableName genTableName
<*> genAnnotatedOrderByElement <*> genAnnotatedOrderByElement
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -558,10 +584,11 @@ genAnnotatedOrderByElement
genA genA
arrayAggregation = arrayAggregation =
AOCArrayAggregation AOCArrayAggregation
<$> genRelInfo genTableName genColumn <$> genRelInfo genTableName genColumnPath
<*> genAnnBoolExp <*> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -573,6 +600,7 @@ genAnnotatedOrderByElement
genTableName genTableName
<*> genAnnotatedAggregateOrderBy <*> genAnnotatedAggregateOrderBy
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -584,6 +612,7 @@ genAnnotatedOrderByElement
AOCComputedField AOCComputedField
<$> genComputedFieldOrderBy <$> genComputedFieldOrderBy
genColumn genColumn
genColumnPath
genScalarType genScalarType
genTableName genTableName
genFunctionName genFunctionName
@ -596,7 +625,9 @@ genAnnotatedAggregateOrderBy ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (TableName b) -> m (TableName b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -607,6 +638,7 @@ genAnnotatedAggregateOrderBy ::
m (AnnotatedAggregateOrderBy b a) m (AnnotatedAggregateOrderBy b a)
genAnnotatedAggregateOrderBy genAnnotatedAggregateOrderBy
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -626,6 +658,7 @@ genAnnotatedAggregateOrderBy
genScalarType genScalarType
<*> genAnnRedactionExp <*> genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -640,7 +673,9 @@ genComputedFieldOrderBy ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (TableName b) -> m (TableName b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -651,6 +686,7 @@ genComputedFieldOrderBy ::
m (ComputedFieldOrderBy b a) m (ComputedFieldOrderBy b a)
genComputedFieldOrderBy genComputedFieldOrderBy
genColumn genColumn
genColumnPath
genScalarType genScalarType
genTableName genTableName
genFunctionName genFunctionName
@ -665,6 +701,7 @@ genComputedFieldOrderBy
<*> genFunctionArgsExpG genFunctionArgumentExp <*> genFunctionArgsExpG genFunctionArgumentExp
<*> genComputedFieldOrderByElement <*> genComputedFieldOrderByElement
genColumn genColumn
genColumnPath
genScalarType genScalarType
genTableName genTableName
genFunctionName genFunctionName
@ -677,7 +714,9 @@ genComputedFieldOrderByElement ::
(MonadGen m) => (MonadGen m) =>
(Hashable (ScalarType b)) => (Hashable (ScalarType b)) =>
(Hashable (Column b)) => (Hashable (Column b)) =>
(Hashable (ColumnPath b)) =>
m (Column b) -> m (Column b) ->
m (ColumnPath b) ->
m (ScalarType b) -> m (ScalarType b) ->
m (TableName b) -> m (TableName b) ->
m (FunctionName b) -> m (FunctionName b) ->
@ -688,6 +727,7 @@ genComputedFieldOrderByElement ::
m (ComputedFieldOrderByElement b a) m (ComputedFieldOrderByElement b a)
genComputedFieldOrderByElement genComputedFieldOrderByElement
genColumn genColumn
genColumnPath
genScalarType genScalarType
genTableName genTableName
genFunctionName genFunctionName
@ -700,6 +740,7 @@ genComputedFieldOrderByElement
<$> genScalarType <$> genScalarType
<*> genAnnRedactionExp <*> genAnnRedactionExp
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -712,6 +753,7 @@ genComputedFieldOrderByElement
<*> genAnnBoolExp <*> genAnnBoolExp
( genAnnBoolExpFld ( genAnnBoolExpFld
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName
@ -723,6 +765,7 @@ genComputedFieldOrderByElement
genTableName genTableName
<*> genAnnotatedAggregateOrderBy <*> genAnnotatedAggregateOrderBy
genColumn genColumn
genColumnPath
genTableName genTableName
genScalarType genScalarType
genFunctionName genFunctionName