feat: validate ?columns mutation targets based on schema cache (#2542)
This returns an error for trying to update or insert into invalid columns, without hitting the database. This change also switches from `json_populate_recordset` for these operations `json_to_recordset` which should make no functional difference except allowing future flexibility.
This commit is contained in:
@@ -4,20 +4,21 @@ module PostgREST.Plan.MutatePlan
|
||||
where
|
||||
|
||||
import qualified Data.ByteString.Lazy as LBS
|
||||
import qualified Data.Set as S
|
||||
|
||||
import PostgREST.ApiRequest.Preferences (PreferResolution)
|
||||
import PostgREST.ApiRequest.Types (LogicTree, OrderTerm)
|
||||
import PostgREST.Plan.Types (TypedField)
|
||||
import PostgREST.RangeQuery (NonnegRange)
|
||||
import PostgREST.SchemaCache.Identifiers (FieldName,
|
||||
QualifiedIdentifier)
|
||||
|
||||
|
||||
import Protolude
|
||||
|
||||
data MutatePlan
|
||||
= Insert
|
||||
{ in_ :: QualifiedIdentifier
|
||||
, insCols :: S.Set FieldName
|
||||
, insCols :: [TypedField]
|
||||
, insBody :: Maybe LBS.ByteString
|
||||
, onConflict :: Maybe (PreferResolution, [FieldName])
|
||||
, where_ :: [LogicTree]
|
||||
@@ -26,7 +27,7 @@ data MutatePlan
|
||||
}
|
||||
| Update
|
||||
{ in_ :: QualifiedIdentifier
|
||||
, updCols :: S.Set FieldName
|
||||
, updCols :: [TypedField]
|
||||
, updBody :: Maybe LBS.ByteString
|
||||
, where_ :: [LogicTree]
|
||||
, mutRange :: NonnegRange
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
module PostgREST.Plan.Types
|
||||
( TypedField(..)
|
||||
, resolveTableField
|
||||
|
||||
) where
|
||||
|
||||
import qualified Data.HashMap.Strict.InsOrd as HMI
|
||||
|
||||
import PostgREST.SchemaCache.Identifiers (FieldName)
|
||||
import PostgREST.SchemaCache.Table (Column (..), Table (..))
|
||||
|
||||
import Protolude
|
||||
|
||||
-- | A TypedField is a field with sufficient information to be read from JSON with `json_to_recordset`.
|
||||
data TypedField = TypedField
|
||||
{ tfName :: FieldName
|
||||
, tfIRType :: Text -- ^ The initial type of the field, before any casting.
|
||||
} deriving (Eq)
|
||||
|
||||
resolveTableField :: Table -> FieldName -> Maybe TypedField
|
||||
resolveTableField table fieldName =
|
||||
case HMI.lookup fieldName (tableColumns table) of
|
||||
Just column -> Just $ TypedField (colName column) (colNominalType column)
|
||||
Nothing -> Nothing
|
||||
Reference in New Issue
Block a user