mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-10-26 18:29:39 +03:00
Nested where
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9940 GitOrigin-RevId: c2115f1de4f647c4b559c98183c6260a1f5674dd
This commit is contained in:
parent
374bbd1937
commit
23d40fc500
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hasura/dc-api-types",
|
||||
"version": "0.34.0",
|
||||
"version": "0.35.0",
|
||||
"description": "Hasura GraphQL Engine Data Connector Agent API types",
|
||||
"author": "Hasura (https://github.com/hasura/graphql-engine)",
|
||||
"license": "Apache-2.0",
|
||||
|
@ -1759,8 +1759,19 @@
|
||||
"$ref": "#/components/schemas/ScalarType"
|
||||
},
|
||||
"name": {
|
||||
"description": "The name of the column",
|
||||
"type": "string"
|
||||
"additionalProperties": true,
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
}
|
||||
],
|
||||
"description": "The name of the column"
|
||||
},
|
||||
"path": {
|
||||
"default": [],
|
||||
|
@ -9,7 +9,7 @@ export type ComparisonColumn = {
|
||||
/**
|
||||
* The name of the column
|
||||
*/
|
||||
name: string;
|
||||
name: (string | Array<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.
|
||||
*/
|
||||
|
10
dc-agents/package-lock.json
generated
10
dc-agents/package-lock.json
generated
@ -24,7 +24,7 @@
|
||||
},
|
||||
"dc-api-types": {
|
||||
"name": "@hasura/dc-api-types",
|
||||
"version": "0.34.0",
|
||||
"version": "0.35.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node16": "^1.0.3",
|
||||
@ -2227,7 +2227,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify": "^4.13.0",
|
||||
"mathjs": "^11.0.0",
|
||||
"pino-pretty": "^8.0.0",
|
||||
@ -2547,7 +2547,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify": "^4.13.0",
|
||||
"fastify-metrics": "^9.2.1",
|
||||
"nanoid": "^3.3.4",
|
||||
@ -2868,7 +2868,7 @@
|
||||
"version": "file:reference",
|
||||
"requires": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"@tsconfig/node16": "^1.0.3",
|
||||
"@types/node": "^16.11.49",
|
||||
"@types/xml2js": "^0.4.11",
|
||||
@ -3080,7 +3080,7 @@
|
||||
"version": "file:sqlite",
|
||||
"requires": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"@tsconfig/node16": "^1.0.3",
|
||||
"@types/node": "^16.11.49",
|
||||
"@types/sqlite3": "^3.1.8",
|
||||
|
4
dc-agents/reference/package-lock.json
generated
4
dc-agents/reference/package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify": "^4.13.0",
|
||||
"mathjs": "^11.0.0",
|
||||
"pino-pretty": "^8.0.0",
|
||||
@ -52,7 +52,7 @@
|
||||
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
|
||||
},
|
||||
"node_modules/@hasura/dc-api-types": {
|
||||
"version": "0.34.0",
|
||||
"version": "0.35.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node16": "^1.0.3",
|
||||
|
@ -22,7 +22,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify": "^4.13.0",
|
||||
"mathjs": "^11.0.0",
|
||||
"pino-pretty": "^8.0.0",
|
||||
|
@ -96,6 +96,12 @@ const getUnaryComparisonOperatorEvaluator = (operator: UnaryComparisonOperator):
|
||||
};
|
||||
};
|
||||
|
||||
const getComparisonColumnSelector = (comparisonColumn: ComparisonColumn): string => {
|
||||
if (typeof comparisonColumn.name === "string")
|
||||
return comparisonColumn.name;
|
||||
return comparisonColumn.name[0];
|
||||
}
|
||||
|
||||
const prettyPrintComparisonColumn = (comparisonColumn: ComparisonColumn): string => {
|
||||
return (comparisonColumn.path ?? []).concat(comparisonColumn.name).map(p => `[${p}]`).join(".");
|
||||
}
|
||||
@ -460,12 +466,12 @@ const addRelationshipFilterToQuery = (row: Record<string, RawScalarValue>, relat
|
||||
const makeGetComparisonColumnValue = (parentQueryRowChain: Record<string, RawScalarValue>[]) => (comparisonColumn: ComparisonColumn, row: Record<string, RawScalarValue>): RawScalarValue => {
|
||||
const path = comparisonColumn.path ?? [];
|
||||
if (path.length === 0) {
|
||||
return coerceUndefinedToNull(row[comparisonColumn.name]);
|
||||
return coerceUndefinedToNull(row[getComparisonColumnSelector(comparisonColumn)]);
|
||||
} else if (path.length === 1 && path[0] === "$") {
|
||||
const queryRow = parentQueryRowChain.length === 0
|
||||
? row
|
||||
: parentQueryRowChain[0];
|
||||
return coerceUndefinedToNull(queryRow[comparisonColumn.name]);
|
||||
return coerceUndefinedToNull(queryRow[getComparisonColumnSelector(comparisonColumn)]);
|
||||
} else {
|
||||
throw new Error(`Unsupported path on ComparisonColumn: ${prettyPrintComparisonColumn(comparisonColumn)}`);
|
||||
}
|
||||
|
4
dc-agents/sqlite/package-lock.json
generated
4
dc-agents/sqlite/package-lock.json
generated
@ -10,7 +10,7 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify": "^4.13.0",
|
||||
"fastify-metrics": "^9.2.1",
|
||||
"nanoid": "^3.3.4",
|
||||
@ -57,7 +57,7 @@
|
||||
"integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
|
||||
},
|
||||
"node_modules/@hasura/dc-api-types": {
|
||||
"version": "0.34.0",
|
||||
"version": "0.35.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"@tsconfig/node16": "^1.0.3",
|
||||
|
@ -22,7 +22,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@fastify/cors": "^8.1.0",
|
||||
"@hasura/dc-api-types": "0.34.0",
|
||||
"@hasura/dc-api-types": "0.35.0",
|
||||
"fastify-metrics": "^9.2.1",
|
||||
"fastify": "^4.13.0",
|
||||
"nanoid": "^3.3.4",
|
||||
|
@ -228,12 +228,13 @@ function generateComparisonColumnFragment(comparisonColumn: ComparisonColumn, qu
|
||||
const path = comparisonColumn.path ?? [];
|
||||
const queryTablePrefix = queryTableAlias ? `${queryTableAlias}.` : '';
|
||||
const currentTablePrefix = currentTableAlias ? `${currentTableAlias}.` : '';
|
||||
const selector = getComparisonColumnSelector(comparisonColumn);
|
||||
if (path.length === 0) {
|
||||
return `${currentTablePrefix}${escapeIdentifier(comparisonColumn.name)}`
|
||||
return `${currentTablePrefix}${escapeIdentifier(selector)}`
|
||||
} else if (path.length === 1 && path[0] === "$") {
|
||||
return `${queryTablePrefix}${escapeIdentifier(comparisonColumn.name)}`
|
||||
return `${queryTablePrefix}${escapeIdentifier(selector)}`
|
||||
} else {
|
||||
throw new Error(`Unsupported path on ComparisonColumn: ${[...path, comparisonColumn.name].join(".")}`);
|
||||
throw new Error(`Unsupported path on ComparisonColumn: ${[...path, selector].join(".")}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -882,3 +883,8 @@ type AnalysisEntry = {
|
||||
detail: string
|
||||
}
|
||||
|
||||
const getComparisonColumnSelector = (comparisonColumn: ComparisonColumn): string => {
|
||||
if (typeof comparisonColumn.name === "string")
|
||||
return comparisonColumn.name;
|
||||
return comparisonColumn.name[0];
|
||||
}
|
||||
|
@ -301,7 +301,7 @@ tests = describe "Basic Tests" $ do
|
||||
(API.UnrelatedTable $ mkTableName "Employee")
|
||||
( API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "EmployeeId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "EmployeeId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 1) (API.ScalarType "number"))
|
||||
)
|
||||
)
|
||||
|
@ -165,27 +165,27 @@ tests = describe "Custom scalar parsing tests" $ do
|
||||
( Set.fromList
|
||||
[ ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyBooleanColumn") (ScalarType "MyBoolean"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyBooleanColumn") (ScalarType "MyBoolean"))
|
||||
(ScalarValueComparison $ ScalarValue (J.Bool True) (ScalarType "MyBoolean")),
|
||||
ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyFloatColumn") (ScalarType "MyFloat"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyFloatColumn") (ScalarType "MyFloat"))
|
||||
(ScalarValueComparison $ ScalarValue (J.Number 3.14) (ScalarType "MyFloat")),
|
||||
ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyStringColumn") (ScalarType "MyString"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyStringColumn") (ScalarType "MyString"))
|
||||
(ScalarValueComparison $ ScalarValue (J.String "foo") (ScalarType "MyString")),
|
||||
ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyIDColumn") (ScalarType "MyID"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyIDColumn") (ScalarType "MyID"))
|
||||
(ScalarValueComparison $ ScalarValue (J.String "x") (ScalarType "MyID")),
|
||||
ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyIntColumn") (ScalarType "MyInt"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyIntColumn") (ScalarType "MyInt"))
|
||||
(ScalarValueComparison $ ScalarValue (J.Number 42.0) (ScalarType "MyInt")),
|
||||
ApplyBinaryComparisonOperator
|
||||
Equal
|
||||
(ComparisonColumn CurrentTable (ColumnName "MyAnythingColumn") (ScalarType "MyAnything"))
|
||||
(ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "MyAnythingColumn") (ScalarType "MyAnything"))
|
||||
(ScalarValueComparison $ ScalarValue (J.Object mempty) (ScalarType "MyAnything"))
|
||||
]
|
||||
)
|
||||
|
@ -204,11 +204,11 @@ tests = do
|
||||
$ Set.fromList
|
||||
[ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 90) (API.ScalarType "number")),
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.GreaterThan
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 111) (API.ScalarType "number"))
|
||||
],
|
||||
API._dmoReturningFields =
|
||||
@ -312,11 +312,11 @@ tests = do
|
||||
$ Set.fromList
|
||||
[ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 90) (API.ScalarType "number")),
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 112) (API.ScalarType "number"))
|
||||
],
|
||||
API._dmoReturningFields =
|
||||
|
@ -221,7 +221,7 @@ tests = do
|
||||
Just
|
||||
$ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "ArtistId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 2) (API.ScalarType "number")),
|
||||
API._imoReturningFields =
|
||||
mkFieldsMap
|
||||
|
@ -417,8 +417,8 @@ tests = describe "Object Relationships Tests" $ do
|
||||
(API.RelatedTable $ API.RelationshipName "SupportRepForCustomers")
|
||||
( API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") $ API.ScalarType "string")
|
||||
(API.AnotherColumnComparison (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") $ API.ScalarType "string"))
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "Country") $ API.ScalarType "string")
|
||||
(API.AnotherColumnComparison (API.ComparisonColumn API.QueryTable (API.mkColumnSelector $ API.ColumnName "Country") $ API.ScalarType "string"))
|
||||
)
|
||||
& API.qOrderBy
|
||||
?~ API.OrderBy
|
||||
@ -429,8 +429,8 @@ tests = describe "Object Relationships Tests" $ do
|
||||
$ API.Exists (API.RelatedTable $ API.RelationshipName "SupportRep")
|
||||
$ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "Country") $ API.ScalarType "string")
|
||||
(API.AnotherColumnComparison (API.ComparisonColumn API.QueryTable (API.ColumnName "Country") $ API.ScalarType "string"))
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "Country") $ API.ScalarType "string")
|
||||
(API.AnotherColumnComparison (API.ComparisonColumn API.QueryTable (API.mkColumnSelector $ API.ColumnName "Country") $ API.ScalarType "string"))
|
||||
)
|
||||
mempty
|
||||
)
|
||||
|
@ -239,18 +239,18 @@ tests = do
|
||||
$ Set.fromList
|
||||
[ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 3) (API.ScalarType "number")),
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "GenreId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "GenreId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 1) (API.ScalarType "number"))
|
||||
],
|
||||
API._umoPostUpdateCheck =
|
||||
Just
|
||||
$ API.ApplyBinaryComparisonOperator
|
||||
API.GreaterThan
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "UnitPrice") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "UnitPrice") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 0) (API.ScalarType "number")),
|
||||
API._umoReturningFields =
|
||||
mkFieldsMap
|
||||
@ -366,7 +366,7 @@ tests = do
|
||||
Just
|
||||
$ API.ApplyBinaryComparisonOperator
|
||||
API.GreaterThan
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "UnitPrice") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "UnitPrice") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 0) (API.ScalarType "number"))
|
||||
let sharedReturning =
|
||||
mkFieldsMap
|
||||
@ -429,11 +429,11 @@ tests = do
|
||||
$ Set.fromList
|
||||
[ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 3) (API.ScalarType "number")),
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "TrackId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "TrackId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 3) (API.ScalarType "number"))
|
||||
],
|
||||
API._umoPostUpdateCheck = sharedPostUpdateCheck,
|
||||
@ -469,11 +469,11 @@ tests = do
|
||||
$ Set.fromList
|
||||
[ API.ApplyBinaryComparisonOperator
|
||||
API.Equal
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "AlbumId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 3) (API.ScalarType "number")),
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.GreaterThan
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "TrackId") $ API.ScalarType "number")
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "TrackId") $ API.ScalarType "number")
|
||||
(API.ScalarValueComparison $ API.ScalarValue (J.Number 3) (API.ScalarType "number"))
|
||||
],
|
||||
API._umoPostUpdateCheck = sharedPostUpdateCheck,
|
||||
|
@ -9,6 +9,8 @@ module Hasura.Backends.DataConnector.API.V0.Expression
|
||||
UnaryComparisonOperator (..),
|
||||
ComparisonColumn (..),
|
||||
ColumnPath (..),
|
||||
ColumnSelector (..),
|
||||
mkColumnSelector,
|
||||
ComparisonValue (..),
|
||||
)
|
||||
where
|
||||
@ -21,6 +23,8 @@ import Data.Aeson (FromJSON, ToJSON, Value)
|
||||
import Data.Data (Data)
|
||||
import Data.HashMap.Strict qualified as HashMap
|
||||
import Data.Hashable (Hashable)
|
||||
import Data.List.NonEmpty (NonEmpty (..))
|
||||
import Data.List.NonEmpty qualified as NonEmpty
|
||||
import Data.OpenApi (ToSchema)
|
||||
import Data.Set (Set)
|
||||
import Data.Text (Text)
|
||||
@ -244,7 +248,7 @@ data ComparisonColumn = ComparisonColumn
|
||||
{ -- | The path to the table that contains the specified column.
|
||||
_ccPath :: ColumnPath,
|
||||
-- | The name of the column
|
||||
_ccName :: API.V0.ColumnName,
|
||||
_ccName :: ColumnSelector,
|
||||
-- | The scalar type of the column
|
||||
_ccColumnType :: API.V0.ScalarType
|
||||
}
|
||||
@ -291,6 +295,20 @@ instance HasCodec ColumnPath where
|
||||
CurrentTable -> []
|
||||
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.
|
||||
data ComparisonValue
|
||||
= -- | Allows a comparison to a column on the current table or another table
|
||||
|
@ -517,8 +517,8 @@ mkTestData schemaResponse testConfig =
|
||||
_tdColumnInsertSchema = columnInsertSchema schemaResponse testConfig,
|
||||
_tdRowColumnOperatorValue = rowColumnOperatorValue schemaResponse testConfig,
|
||||
_tdFindColumnScalarType = \tableName name -> findColumnScalarType schemaResponse tableName (formatColumnName testConfig $ API.ColumnName name),
|
||||
_tdQueryComparisonColumn = API.ComparisonColumn API.QueryTable . formatColumnName testConfig . API.ColumnName,
|
||||
_tdCurrentComparisonColumn = API.ComparisonColumn API.CurrentTable . formatColumnName testConfig . API.ColumnName,
|
||||
_tdQueryComparisonColumn = API.ComparisonColumn API.QueryTable . API.mkColumnSelector . formatColumnName testConfig . API.ColumnName,
|
||||
_tdCurrentComparisonColumn = API.ComparisonColumn API.CurrentTable . API.mkColumnSelector . formatColumnName testConfig . API.ColumnName,
|
||||
_tdOrderByColumn = \targetPath name -> orderByColumn targetPath (formatColumnName testConfig $ API.ColumnName name)
|
||||
}
|
||||
where
|
||||
@ -561,7 +561,7 @@ mkEdgeCasesTestData testConfig schemaResponse =
|
||||
_ectdColumnField = columnField schemaResponse testConfig,
|
||||
_ectdMkDefaultTableInsertSchema = mkDefaultTableInsertSchema schemaResponse testConfig edgeCasesSchemaTables,
|
||||
_ectdRowColumnOperatorValue = rowColumnOperatorValue schemaResponse testConfig,
|
||||
_ectdCurrentComparisonColumn = API.ComparisonColumn API.CurrentTable . formatColumnName testConfig . API.ColumnName
|
||||
_ectdCurrentComparisonColumn = API.ComparisonColumn API.CurrentTable . API.mkColumnSelector . formatColumnName testConfig . API.ColumnName
|
||||
}
|
||||
where
|
||||
tableExists :: API.TableName -> Bool
|
||||
|
@ -47,7 +47,7 @@ spec TestData {..} (ScalarTypesCapabilities scalarTypesCapabilities) = describe
|
||||
ApplyBinaryComparisonOperator
|
||||
(CustomBinaryComparisonOperator (unName operatorName))
|
||||
(_tdCurrentComparisonColumn (unColumnName columnName) columnType)
|
||||
(AnotherColumnComparison $ ComparisonColumn CurrentTable argColumnName argType)
|
||||
(AnotherColumnComparison $ ComparisonColumn CurrentTable (mkColumnSelector argColumnName) argType)
|
||||
query =
|
||||
queryRequest
|
||||
& qrQuery . qWhere ?~ where'
|
||||
|
@ -130,7 +130,7 @@ spec testConfig API.Capabilities {} = describe "supports functions" $ preloadAge
|
||||
whereClause =
|
||||
API.ApplyBinaryComparisonOperator
|
||||
API.LessThan
|
||||
(API.ComparisonColumn API.CurrentTable (API.ColumnName "id") (API.ScalarType "number"))
|
||||
(API.ComparisonColumn API.CurrentTable (API.mkColumnSelector $ API.ColumnName "id") (API.ScalarType "number"))
|
||||
(API.ScalarValueComparison (API.ScalarValue (Number 10) (API.ScalarType "number")))
|
||||
query' = Data.emptyQuery & qFields ?~ fields & qWhere ?~ whereClause & qLimit ?~ 2
|
||||
authorRelationship =
|
||||
|
@ -37,6 +37,7 @@ module Autodocodec.Extended
|
||||
fromEnvCodec,
|
||||
optionalVersionField,
|
||||
versionField,
|
||||
oneOrManyCodec,
|
||||
module Autodocodec,
|
||||
)
|
||||
where
|
||||
@ -431,3 +432,12 @@ discriminatorBoolField name value =
|
||||
-- reference.
|
||||
fromEnvCodec :: JSONCodec Text
|
||||
fromEnvCodec = object "FromEnv" $ requiredField' "from_env"
|
||||
|
||||
oneOrManyCodec :: forall a. (HasCodec a) => JSONCodec [a]
|
||||
oneOrManyCodec =
|
||||
matchChoiceCodec singletonCodec (codec @[a]) chooser
|
||||
where
|
||||
singletonCodec = dimapCodec pure id (codec @a)
|
||||
chooser = \case
|
||||
[x] -> Left x
|
||||
xs -> Right xs
|
||||
|
@ -36,6 +36,7 @@ import Data.Bifunctor (Bifunctor (bimap))
|
||||
import Data.ByteString qualified as BS
|
||||
import Data.Has
|
||||
import Data.HashMap.Strict qualified as HashMap
|
||||
import Data.List.NonEmpty qualified as NonEmpty
|
||||
import Data.Set (Set)
|
||||
import Data.Set qualified as Set
|
||||
import Data.Text qualified as T
|
||||
@ -221,6 +222,20 @@ parseSessionVariable varName varType varValue = do
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
newtype ColumnStack = ColumnStack [ColumnName]
|
||||
|
||||
emptyColumnStack :: ColumnStack
|
||||
emptyColumnStack = ColumnStack []
|
||||
|
||||
pushColumn :: ColumnStack -> ColumnName -> ColumnStack
|
||||
pushColumn (ColumnStack stack) columnName = ColumnStack $ columnName : stack
|
||||
|
||||
toColumnSelector :: ColumnStack -> ColumnName -> API.ColumnSelector
|
||||
toColumnSelector (ColumnStack stack) columnName =
|
||||
API.ColumnSelector $ NonEmpty.reverse $ Witch.from columnName :| fmap Witch.from stack
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
translateBoolExpToExpression ::
|
||||
( Has TableRelationships writerOutput,
|
||||
Monoid writerOutput,
|
||||
@ -233,7 +248,7 @@ translateBoolExpToExpression ::
|
||||
AnnBoolExp 'DataConnector (UnpreparedValue 'DataConnector) ->
|
||||
CPS.WriterT writerOutput m (Maybe API.Expression)
|
||||
translateBoolExpToExpression sessionVariables sourceName boolExp = do
|
||||
removeAlwaysTrueExpression <$> translateBoolExp sessionVariables sourceName boolExp
|
||||
removeAlwaysTrueExpression <$> translateBoolExp sessionVariables sourceName emptyColumnStack boolExp
|
||||
|
||||
translateBoolExp ::
|
||||
( Has TableRelationships writerOutput,
|
||||
@ -244,25 +259,29 @@ translateBoolExp ::
|
||||
) =>
|
||||
SessionVariables ->
|
||||
TableRelationshipsKey ->
|
||||
ColumnStack ->
|
||||
AnnBoolExp 'DataConnector (UnpreparedValue 'DataConnector) ->
|
||||
CPS.WriterT writerOutput m API.Expression
|
||||
translateBoolExp sessionVariables sourceName = \case
|
||||
translateBoolExp sessionVariables sourceName columnStack = \case
|
||||
BoolAnd xs ->
|
||||
mkIfZeroOrMany API.And . mapMaybe removeAlwaysTrueExpression <$> traverse (translateBoolExp' sourceName) xs
|
||||
mkIfZeroOrMany API.And . mapMaybe removeAlwaysTrueExpression <$> traverse (translateBoolExp' sourceName columnStack) xs
|
||||
BoolOr xs ->
|
||||
mkIfZeroOrMany API.Or . mapMaybe removeAlwaysFalseExpression <$> traverse (translateBoolExp' sourceName) xs
|
||||
mkIfZeroOrMany API.Or . mapMaybe removeAlwaysFalseExpression <$> traverse (translateBoolExp' sourceName columnStack) xs
|
||||
BoolNot x ->
|
||||
API.Not <$> (translateBoolExp' sourceName) x
|
||||
BoolField (AVColumn c _redactionExp opExps) ->
|
||||
API.Not <$> (translateBoolExp' sourceName columnStack) x
|
||||
BoolField (AVColumn c _redactionExp opExps) -> do
|
||||
-- TODO(redactionExp): Deal with the redaction expression
|
||||
lift $ mkIfZeroOrMany API.And <$> traverse (translateOp sessionVariables (Witch.from $ ciColumn c) (Witch.from . columnTypeToScalarType $ ciType c)) opExps
|
||||
let columnSelector = toColumnSelector columnStack $ ciColumn c
|
||||
lift $ mkIfZeroOrMany API.And <$> traverse (translateOp sessionVariables columnSelector (Witch.from . columnTypeToScalarType $ ciType c)) opExps
|
||||
BoolField (AVNestedObject NestedObjectInfo {..} nestedExp) ->
|
||||
translateBoolExp' sourceName (pushColumn columnStack _noiColumn) nestedExp
|
||||
BoolField (AVRelationship relationshipInfo (RelationshipFilters {rfTargetTablePermissions, rfFilter})) -> do
|
||||
(relationshipName, API.Relationship {..}) <- recordTableRelationshipFromRelInfo sourceName relationshipInfo
|
||||
-- TODO: How does this function keep track of the root table?
|
||||
API.Exists (API.RelatedTable relationshipName) <$> translateBoolExp' (TableNameKey _rTargetTable) (BoolAnd [rfTargetTablePermissions, rfFilter])
|
||||
API.Exists (API.RelatedTable relationshipName) <$> translateBoolExp' (TableNameKey _rTargetTable) emptyColumnStack (BoolAnd [rfTargetTablePermissions, rfFilter])
|
||||
BoolExists GExists {..} ->
|
||||
let tableName = Witch.from _geTable
|
||||
in API.Exists (API.UnrelatedTable tableName) <$> translateBoolExp' (TableNameKey tableName) _geWhere
|
||||
in API.Exists (API.UnrelatedTable tableName) <$> translateBoolExp' (TableNameKey tableName) emptyColumnStack _geWhere
|
||||
where
|
||||
translateBoolExp' = translateBoolExp sessionVariables
|
||||
|
||||
@ -288,7 +307,7 @@ removeAlwaysFalseExpression = \case
|
||||
translateOp ::
|
||||
(MonadError QErr m, MonadReader r m, Has API.ScalarTypesCapabilities r) =>
|
||||
SessionVariables ->
|
||||
API.ColumnName ->
|
||||
API.ColumnSelector ->
|
||||
API.ScalarType ->
|
||||
OpExpG 'DataConnector (UnpreparedValue 'DataConnector) ->
|
||||
m API.Expression
|
||||
@ -358,7 +377,9 @@ translateOp sessionVariables columnName columnType opExp = do
|
||||
let columnPath = case rootOrCurrent of
|
||||
IsRoot -> API.QueryTable
|
||||
IsCurrent -> API.CurrentTable
|
||||
in API.ApplyBinaryComparisonOperator operator currentComparisonColumn (API.AnotherColumnComparison $ API.ComparisonColumn columnPath (Witch.from otherColumnName) columnType)
|
||||
otherColumnSelector = API.mkColumnSelector $ Witch.from otherColumnName
|
||||
in -- TODO(dmoverton): allow otherColumnName to refer to nested object fields.
|
||||
API.ApplyBinaryComparisonOperator operator currentComparisonColumn (API.AnotherColumnComparison $ API.ComparisonColumn columnPath otherColumnSelector columnType)
|
||||
|
||||
inOperator :: Literal -> API.Expression
|
||||
inOperator literal =
|
||||
|
@ -12,6 +12,7 @@ module Hasura.GraphQL.Schema.BoolExp
|
||||
where
|
||||
|
||||
import Data.Has (getter)
|
||||
import Data.HashMap.Strict qualified as HashMap
|
||||
import Data.Text.Casing (GQLNameIdentifier)
|
||||
import Data.Text.Casing qualified as C
|
||||
import Data.Text.Extended
|
||||
@ -137,7 +138,12 @@ boolExpInternal gqlName selectPermissions fieldInfos description memoizeKey mkAg
|
||||
FIColumn (SCIScalarColumn columnInfo) ->
|
||||
let redactionExp = fromMaybe NoRedaction $ getRedactionExprForColumn selectPermissions' (ciColumn columnInfo)
|
||||
in lift $ fmap (AVColumn columnInfo redactionExp) <$> comparisonExps @b (ciType columnInfo)
|
||||
FIColumn (SCIObjectColumn _) -> empty -- TODO(dmoverton)
|
||||
FIColumn (SCIObjectColumn nestedObjectInfo@NestedObjectInfo {..}) -> do
|
||||
SourceInfo {..} <- asks getter
|
||||
logicalModelInfo <-
|
||||
HashMap.lookup _noiType _siLogicalModels
|
||||
`onNothing` throw500 ("Logical model " <> _noiType <<> " not found in source " <>> _siName)
|
||||
lift $ fmap (AVNestedObject nestedObjectInfo) <$> logicalModelBoolExp logicalModelInfo
|
||||
FIColumn (SCIArrayColumn _) -> empty -- TODO(dmoverton)
|
||||
-- field_name: field_type_bool_exp
|
||||
FIRelationship relationshipInfo -> do
|
||||
@ -192,32 +198,30 @@ logicalModelBoolExp ::
|
||||
SchemaT r m (Parser 'Input n (AnnBoolExp b (UnpreparedValue b)))
|
||||
logicalModelBoolExp logicalModel = do
|
||||
roleName <- retrieve scRole
|
||||
case toFieldInfo (columnsFromFields $ _lmiFields logicalModel) of
|
||||
Nothing -> throw500 $ "Error creating fields for logical model " <> tshow (_lmiName logicalModel)
|
||||
Just fieldInfo -> do
|
||||
let name = getLogicalModelName (_lmiName logicalModel)
|
||||
gqlName = mkTableBoolExpTypeName (C.fromCustomName name)
|
||||
selectPermissions = getSelPermInfoForLogicalModel roleName logicalModel
|
||||
let fieldInfos = HashMap.elems $ logicalModelFieldsToFieldInfo $ _lmiFields logicalModel
|
||||
name = getLogicalModelName (_lmiName logicalModel)
|
||||
gqlName = mkTableBoolExpTypeName (C.fromCustomName name)
|
||||
selectPermissions = getSelPermInfoForLogicalModel roleName logicalModel
|
||||
|
||||
-- Aggregation parsers let us say things like, "select all authors
|
||||
-- with at least one article": they are predicates based on the
|
||||
-- object's relationship with some other entity.
|
||||
--
|
||||
-- Currently, logical models can't be defined to have
|
||||
-- relationships to other entities, and so they don't support
|
||||
-- aggregation predicates.
|
||||
--
|
||||
-- If you're here because you've been asked to implement them, this
|
||||
-- is where you want to put the parser.
|
||||
mkAggPredParser = pure (pure mempty)
|
||||
-- Aggregation parsers let us say things like, "select all authors
|
||||
-- with at least one article": they are predicates based on the
|
||||
-- object's relationship with some other entity.
|
||||
--
|
||||
-- Currently, logical models can't be defined to have
|
||||
-- relationships to other entities, and so they don't support
|
||||
-- aggregation predicates.
|
||||
--
|
||||
-- If you're here because you've been asked to implement them, this
|
||||
-- is where you want to put the parser.
|
||||
mkAggPredParser = pure (pure mempty)
|
||||
|
||||
memoizeKey = name
|
||||
description =
|
||||
G.Description
|
||||
$ "Boolean expression to filter rows from the logical model for "
|
||||
<> name
|
||||
<<> ". All fields are combined with a logical 'AND'."
|
||||
in boolExpInternal gqlName selectPermissions fieldInfo description memoizeKey mkAggPredParser
|
||||
memoizeKey = name
|
||||
description =
|
||||
G.Description
|
||||
$ "Boolean expression to filter rows from the logical model for "
|
||||
<> name
|
||||
<<> ". All fields are combined with a logical 'AND'."
|
||||
boolExpInternal gqlName selectPermissions fieldInfos description memoizeKey mkAggPredParser
|
||||
|
||||
-- |
|
||||
-- > input type_bool_exp {
|
||||
|
@ -12,11 +12,11 @@ import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
|
||||
import Data.Text.Extended (ToTxt (toTxt))
|
||||
import Hasura.LogicalModel.Cache
|
||||
import Hasura.LogicalModel.NullableScalarType (NullableScalarType (..))
|
||||
import Hasura.LogicalModel.Types (LogicalModelField (..), LogicalModelType (..), LogicalModelTypeScalar (..))
|
||||
import Hasura.LogicalModel.Types (LogicalModelField (..), LogicalModelType (..), LogicalModelTypeArray (..), LogicalModelTypeReference (..), LogicalModelTypeScalar (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp (AnnRedactionExp (..), gBoolExpTrue)
|
||||
import Hasura.RQL.Types.Backend (Backend (..))
|
||||
import Hasura.RQL.Types.Column (ColumnInfo (..), ColumnMutability (..), ColumnType (..), StructuredColumnInfo (..), fromCol)
|
||||
import Hasura.RQL.Types.Column (ColumnInfo (..), ColumnMutability (..), ColumnType (..), NestedArrayInfo (..), NestedObjectInfo (..), StructuredColumnInfo (..), fromCol)
|
||||
import Hasura.RQL.Types.Permission (AllowedRootFields (..))
|
||||
import Hasura.RQL.Types.Roles (RoleName, adminRoleName)
|
||||
import Hasura.Table.Cache (FieldInfo (..), FieldInfoMap, RolePermInfo (..), SelPermInfo (..))
|
||||
@ -55,9 +55,7 @@ logicalModelToColumnInfo :: forall b. (Backend b) => Int -> (Column b, NullableS
|
||||
logicalModelToColumnInfo i (column, NullableScalarType {..}) = do
|
||||
name <- G.mkName (toTxt column)
|
||||
pure
|
||||
$
|
||||
-- TODO(dmoverton): handle object and array columns
|
||||
SCIScalarColumn
|
||||
$ SCIScalarColumn
|
||||
$ ColumnInfo
|
||||
{ ciColumn = column,
|
||||
ciName = name,
|
||||
@ -76,11 +74,51 @@ logicalModelFieldsToFieldInfo ::
|
||||
logicalModelFieldsToFieldInfo =
|
||||
HashMap.fromList
|
||||
. fmap (bimap (fromCol @b) FIColumn)
|
||||
. fromMaybe mempty
|
||||
. traverseWithIndex
|
||||
(\i (column, lmf) -> (,) column <$> logicalModelToColumnInfo i (column, lmf))
|
||||
. catMaybes
|
||||
. zipWith (\i (column, lmf) -> (column,) <$> logicalModelFieldToStructuredColumnInfo i lmf) [0 ..]
|
||||
. InsOrdHashMap.toList
|
||||
. columnsFromFields
|
||||
where
|
||||
logicalModelFieldToStructuredColumnInfo :: Int -> LogicalModelField b -> Maybe (StructuredColumnInfo b)
|
||||
logicalModelFieldToStructuredColumnInfo i LogicalModelField {..} = go lmfType
|
||||
where
|
||||
go = \case
|
||||
LogicalModelTypeScalar LogicalModelTypeScalarC {..} -> do
|
||||
name <- G.mkName (toTxt lmfName)
|
||||
pure
|
||||
$ SCIScalarColumn
|
||||
$ ColumnInfo
|
||||
{ ciColumn = lmfName,
|
||||
ciName = name,
|
||||
ciPosition = i,
|
||||
ciType = ColumnScalar lmtsScalar,
|
||||
ciIsNullable = lmtsNullable,
|
||||
ciDescription = G.Description <$> lmfDescription,
|
||||
ciMutability = ColumnMutability {_cmIsInsertable = False, _cmIsUpdatable = False}
|
||||
}
|
||||
LogicalModelTypeArray LogicalModelTypeArrayC {..} -> do
|
||||
supportsNestedObjects <- eitherToMaybe $ backendSupportsNestedObjects @b
|
||||
arrayColumnInfo <- go lmtaArray
|
||||
pure
|
||||
$ SCIArrayColumn
|
||||
$ NestedArrayInfo
|
||||
{ _naiSupportsNestedArrays = supportsNestedObjects,
|
||||
_naiIsNullable = lmtaNullable,
|
||||
_naiColumnInfo = arrayColumnInfo
|
||||
}
|
||||
LogicalModelTypeReference LogicalModelTypeReferenceC {..} -> do
|
||||
supportsNestedObjects <- eitherToMaybe $ backendSupportsNestedObjects @b
|
||||
name <- G.mkName (toTxt lmfName)
|
||||
pure
|
||||
$ SCIObjectColumn
|
||||
$ NestedObjectInfo
|
||||
{ _noiSupportsNestedObjects = supportsNestedObjects,
|
||||
_noiColumn = lmfName,
|
||||
_noiName = name,
|
||||
_noiType = lmtrReference,
|
||||
_noiIsNullable = lmtrNullable,
|
||||
_noiDescription = G.Description <$> lmfDescription,
|
||||
_noiMutability = ColumnMutability {_cmIsInsertable = False, _cmIsUpdatable = False}
|
||||
}
|
||||
|
||||
getSelPermInfoForLogicalModel ::
|
||||
(Backend b) =>
|
||||
|
@ -499,6 +499,7 @@ instance
|
||||
-- This type is parameterized over the type of leaf values, the values on which we operate.
|
||||
data AnnBoolExpFld (backend :: BackendType) leaf
|
||||
= AVColumn (ColumnInfo backend) (AnnRedactionExp backend leaf) [OpExpG backend leaf]
|
||||
| AVNestedObject (NestedObjectInfo backend) (AnnBoolExp backend leaf)
|
||||
| AVRelationship
|
||||
(RelInfo backend)
|
||||
(RelationshipFilters backend leaf)
|
||||
@ -555,6 +556,10 @@ instance
|
||||
( K.fromText $ toTxt $ ciColumn pci,
|
||||
toJSON (pci, object . pure . toJSONKeyValue <$> opExps)
|
||||
)
|
||||
AVNestedObject noi boolExp ->
|
||||
( K.fromText $ toTxt $ _noiColumn noi,
|
||||
toJSON (noi, boolExp)
|
||||
)
|
||||
AVRelationship ri filters ->
|
||||
( K.fromText $ relNameToTxt $ riName ri,
|
||||
toJSON (ri, toJSON filters)
|
||||
|
@ -789,6 +789,8 @@ getLogicalModelColExpDeps source logicalModelLocation = \case
|
||||
AVRelationship {} -> []
|
||||
AVComputedField _ -> []
|
||||
AVAggregationPredicates _ -> []
|
||||
AVNestedObject NestedObjectInfo {..} boolExp ->
|
||||
getLogicalModelBoolExpDeps source (LMLLogicalModel _noiType) boolExp
|
||||
AVColumn colInfo _redactionExp opExps -> do
|
||||
let columnName :: Column b
|
||||
columnName = ciColumn colInfo
|
||||
@ -851,6 +853,8 @@ getColExpDeps bexp = do
|
||||
colDepReason = bool DRSessionVariable DROnType $ any hasStaticExp opExps
|
||||
colDep = mkColDep @b colDepReason source currTable columnName
|
||||
in (colDep :) <$> getOpExpDeps opExps
|
||||
AVNestedObject NestedObjectInfo {..} boolExp ->
|
||||
pure $ getLogicalModelBoolExpDeps source (LMLLogicalModel _noiType) boolExp
|
||||
AVRelationship relInfo RelationshipFilters {rfTargetTablePermissions, rfFilter} ->
|
||||
case riTarget relInfo of
|
||||
RelTargetNativeQuery _ -> error "getColExpDeps RelTargetNativeQuery"
|
||||
|
@ -68,7 +68,7 @@ spec = do
|
||||
|
||||
describe "ComparisonColumn" $ do
|
||||
testToFromJSONToSchema
|
||||
(ComparisonColumn QueryTable (ColumnName "column_name") (ScalarType "string"))
|
||||
(ComparisonColumn QueryTable (mkColumnSelector $ ColumnName "column_name") (ScalarType "string"))
|
||||
[aesonQQ|{"path": ["$"], "name": "column_name", "column_type": "string"}|]
|
||||
|
||||
jsonOpenApiProperties genComparisonColumn
|
||||
@ -80,10 +80,17 @@ spec = do
|
||||
$ testToFromJSONToSchema CurrentTable [aesonQQ|[]|]
|
||||
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 "AnotherColumnComparison"
|
||||
$ testToFromJSONToSchema
|
||||
(AnotherColumnComparison $ ComparisonColumn CurrentTable (ColumnName "my_column_name") (ScalarType "string"))
|
||||
(AnotherColumnComparison $ ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "my_column_name") (ScalarType "string"))
|
||||
[aesonQQ|{"type": "column", "column": {"name": "my_column_name", "column_type": "string"}}|]
|
||||
describe "ScalarValueComparison"
|
||||
$ testToFromJSONToSchema
|
||||
@ -112,7 +119,7 @@ spec = do
|
||||
jsonOpenApiProperties genExistsInTable
|
||||
|
||||
describe "Expression" $ do
|
||||
let comparisonColumn = ComparisonColumn CurrentTable (ColumnName "my_column_name") (ScalarType "string")
|
||||
let comparisonColumn = ComparisonColumn CurrentTable (mkColumnSelector $ ColumnName "my_column_name") (ScalarType "string")
|
||||
let scalarValue = ScalarValueComparison $ ScalarValue (String "scalar value") (ScalarType "string")
|
||||
let scalarValues = [String "scalar value"]
|
||||
let unaryComparisonExpression = ApplyUnaryComparisonOperator IsNull comparisonColumn
|
||||
@ -247,13 +254,17 @@ genComparisonColumn :: (MonadGen m, GenBase m ~ Identity) => m ComparisonColumn
|
||||
genComparisonColumn =
|
||||
ComparisonColumn
|
||||
<$> genColumnPath
|
||||
<*> genColumnName
|
||||
<*> genColumnSelector
|
||||
<*> genScalarType
|
||||
|
||||
genColumnPath :: (MonadGen m) => m ColumnPath
|
||||
genColumnPath =
|
||||
Gen.element [CurrentTable, QueryTable]
|
||||
|
||||
genColumnSelector :: (MonadGen m) => m ColumnSelector
|
||||
genColumnSelector =
|
||||
ColumnSelector <$> Gen.nonEmpty defaultRange genColumnName
|
||||
|
||||
genComparisonValue :: (MonadGen m, GenBase m ~ Identity) => m ComparisonValue
|
||||
genComparisonValue =
|
||||
Gen.choice
|
||||
|
Loading…
Reference in New Issue
Block a user