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:
Alexander Ljungberg
2023-01-07 22:08:30 -05:00
committed by GitHub
parent 5a0f83ecb8
commit 43ad6d6aa0
14 changed files with 174 additions and 52 deletions
+4 -3
View File
@@ -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
+24
View File
@@ -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