Fixed filtering not being applied across object relations in SQLite agent

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6937
GitOrigin-RevId: 655e9be98059a1e86566b975ae646b49d67fa06e
This commit is contained in:
Daniel Chambers 2022-11-18 19:14:04 +11:00 committed by hasura-bot
parent 7228d0327f
commit 7e9f5bdd96
2 changed files with 59 additions and 38 deletions

View File

@ -294,7 +294,7 @@ type RelationshipJoinInfo = {
columnMapping: Record<string, string> // Mapping from source table column name to target table column name
}
function array_relationship(
function table_query(
ts: TableRelationships[],
tableName: TableName,
joinInfo: RelationshipJoinInfo | null,
@ -325,20 +325,7 @@ function array_relationship(
}
})()
return tag('array_relationship',`(SELECT JSON_OBJECT(${[...fieldSelect, ...aggregateSelect].join(', ')}) ${fieldFrom})`);
}
function object_relationship(
ts: TableRelationships[],
targetTable: TableName,
joinInfo: RelationshipJoinInfo,
fields: Fields,
): string {
const targetTableAlias = generateTableAlias(targetTable);
const innerFrom = `${escapeTableName(targetTable)} AS ${targetTableAlias}`;
const whereClause = where(ts, null, joinInfo, targetTable, targetTableAlias);
return tag('object_relationship',
`(SELECT JSON_OBJECT('rows', JSON_ARRAY(${json_object(ts, fields, targetTable, targetTableAlias)})) AS j FROM ${innerFrom} ${whereClause})`);
return tag('table_query',`(SELECT JSON_OBJECT(${[...fieldSelect, ...aggregateSelect].join(', ')}) ${fieldFrom})`);
}
function relationship(ts: TableRelationships[], r: Relationship, field: RelationshipField, sourceTableAlias: string): string {
@ -348,28 +335,24 @@ function relationship(ts: TableRelationships[], r: Relationship, field: Relation
columnMapping: r.column_mapping,
};
switch(r.relationship_type) {
case 'object':
return tag('relationship', object_relationship(
ts,
r.target_table,
relationshipJoinInfo,
coerceUndefinedOrNullToEmptyRecord(field.query.fields),
));
// We force a limit of 1 for object relationships in case the user has configured a manual
// "object" relationship that accidentally actually is an array relationship
const limit =
r.relationship_type === "object"
? 1
: coerceUndefinedToNull(field.query.limit);
case 'array':
return tag('relationship', array_relationship(
ts,
r.target_table,
relationshipJoinInfo,
coerceUndefinedOrNullToEmptyRecord(field.query.fields),
coerceUndefinedOrNullToEmptyRecord(field.query.aggregates),
coerceUndefinedToNull(field.query.where),
coerceUndefinedToNull(field.query.limit),
coerceUndefinedToNull(field.query.offset),
coerceUndefinedToNull(field.query.order_by),
));
}
return tag("relationship", table_query(
ts,
r.target_table,
relationshipJoinInfo,
coerceUndefinedOrNullToEmptyRecord(field.query.fields),
coerceUndefinedOrNullToEmptyRecord(field.query.aggregates),
coerceUndefinedToNull(field.query.where),
limit,
coerceUndefinedToNull(field.query.offset),
coerceUndefinedToNull(field.query.order_by),
));
}
function bop_array(o: BinaryArrayComparisonOperator): string {
@ -625,7 +608,7 @@ function offset(o: number | null): string {
/** Top-Level Query Function.
*/
function query(request: QueryRequest): string {
const result = array_relationship(
const result = table_query(
request.table_relationships,
request.table,
null,

View File

@ -3,11 +3,12 @@ module Test.QuerySpec.RelationshipsSpec (spec) where
import Control.Arrow ((>>>))
import Control.Lens (Traversal', ix, (&), (?~), (^.), (^..), (^?), _Just)
import Control.Monad (when)
import Data.Aeson (Value (..))
import Data.HashMap.Strict (HashMap)
import Data.List (sortOn)
import Data.List.NonEmpty (NonEmpty (..))
import Data.List.NonEmpty qualified as NonEmpty
import Data.Maybe (maybeToList)
import Data.Maybe (fromMaybe, maybeToList)
import Hasura.Backends.DataConnector.API
import Servant.API (NamedRoutes)
import Servant.Client (Client)
@ -65,6 +66,43 @@ spec TestData {..} api sourceName config subqueryComparisonCapabilities = descri
Data.responseRows receivedArtists `rowsShouldBe` expectedAlbums
_qrAggregates receivedArtists `jsonShouldBe` Nothing
it "can filter in object relationships" $ do
let artistWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Name" _tdStringType) (ScalarValue (String "H") _tdStringType)
let query = albumsWithArtistQuery (qWhere ?~ artistWhere)
receivedAlbums <- Data.sortResponseRowsBy "AlbumId" <$> guardedQuery api sourceName config query
let joinInArtist (album :: HashMap FieldName FieldValue) =
let artist = do
artistId <- album ^? Data.field "ArtistId" . Data._ColumnFieldNumber
artist' <- _tdArtistsRowsById ^? ix artistId
if (artist' ^? Data.field "Name" . Data._ColumnFieldString) >= Just "H" then Just artist' else Nothing
artistPropVal = maybeToList artist
in Data.insertField "Artist" (mkSubqueryResponse artistPropVal) album
let removeArtistId = Data.deleteField "ArtistId"
let expectedAlbums = (removeArtistId . joinInArtist) <$> _tdAlbumsRows
Data.responseRows receivedAlbums `rowsShouldBe` expectedAlbums
_qrAggregates receivedAlbums `jsonShouldBe` Nothing
it "can filter in array relationships" $ do
let albumsWhere = ApplyBinaryComparisonOperator GreaterThanOrEqual (_tdCurrentComparisonColumn "Title" _tdStringType) (ScalarValue (String "O") _tdStringType)
let query = artistsWithAlbumsQuery (qWhere ?~ albumsWhere)
receivedArtists <- Data.sortResponseRowsBy "ArtistId" <$> guardedQuery api sourceName config query
let joinInAlbums (artist :: HashMap FieldName FieldValue) =
let albums = fromMaybe [] $ do
artistId <- artist ^? Data.field "ArtistId" . Data._ColumnFieldNumber
_tdAlbumsRows
& filter (\album -> album ^? Data.field "ArtistId" . Data._ColumnFieldNumber == Just artistId && album ^? Data.field "Title" . Data._ColumnFieldString >= Just "O")
& fmap (Data.deleteField "ArtistId")
& sortOn (^? Data.field "ArtistId")
& pure
in Data.insertField "Albums" (mkSubqueryResponse albums) artist
let expectedAlbums = joinInAlbums <$> _tdArtistsRows
Data.responseRows receivedArtists `rowsShouldBe` expectedAlbums
_qrAggregates receivedArtists `jsonShouldBe` Nothing
when ((_ctccSupportsRelations <$> subqueryComparisonCapabilities) == Just True) $
describe "Cross related table comparisons" $ do
it "perform an object relationship query by joining employee to customers and filter comparing columns across the object relationship" $ do