See PR #2523. Most notable code changes: - Load data representation casts into schema cache. - Data representations for reads, filters, inserts, updates, views, over joins. - `CoercibleField` represents name references in queries where coercion may be needed. - `ResolverContext` help facilitate field resolution during planning. - Planner 'resolves' names in the API query and pairs them with any implicit conversions to be used in the query builder stage. - Tests for all of the above. - More consistent naming (TypedX -> CoercibleX). New: unit tests for more data representation use cases; helpful as examples as well. New: update CHANGELOG with data representations feature description. Fixed failing idempotence test. New: replace date formatter test with one that does something. Fixup: inadvertent CHANGELOG change after rebase. Cleanup: `tfName` -> `cfName` and related. Document what IRType means. Formatting. New: use a subquery to interpret `IN` literals requiring data rep transformation. - With the previous method, very long queries such as `ANY (ARRAY[test.color('000100'), test.color('CAFE12'), test.color('01E240'), ...` could be generated. Consider the case where the parser function name is 45 characters and there's a hundred literals. That's 4.5kB of SQL just for the function name alone! - New version uses `unnest`: `ANY (SELECT test.color(unnest('{000100,CAFE12,01E240,...}'::text[]))` to produce a much shorter query. - This is likely to be more performant and either way much more readable and debuggable in the logs.
30 lines
1.2 KiB
Haskell
30 lines
1.2 KiB
Haskell
{-# LANGUAGE DeriveAnyClass #-}
|
|
{-# LANGUAGE DeriveGeneric #-}
|
|
|
|
module PostgREST.SchemaCache.Representations
|
|
( DataRepresentation(..)
|
|
, RepresentationsMap
|
|
) where
|
|
|
|
import qualified Data.Aeson as JSON
|
|
import qualified Data.HashMap.Strict as HM
|
|
|
|
|
|
import Protolude
|
|
|
|
-- | Data representations allow user customisation of how to present and receive data through APIs, per field.
|
|
-- This structure is used for the library of available transforms. It answers questions like:
|
|
-- - What function, if any, should be used to present a certain field that's been selected for API output?
|
|
-- - How do we parse incoming data for a certain field type when inserting or updating?
|
|
-- - And similarly, how do we parse textual data in a query string to be used as a filter?
|
|
--
|
|
-- Support for outputting special formats like CSV and binary data would fit into the same system.
|
|
data DataRepresentation = DataRepresentation
|
|
{ drSourceType :: Text
|
|
, drTargetType :: Text
|
|
, drFunction :: Text
|
|
} deriving (Eq, Show, Generic, JSON.ToJSON, JSON.FromJSON)
|
|
|
|
-- The representation map maps from (source type, target type) to a DR.
|
|
type RepresentationsMap = HM.HashMap (Text, Text) DataRepresentation
|