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:
@@ -26,13 +26,14 @@ module PostgREST.SchemaCache
|
||||
, schemaDescription
|
||||
) where
|
||||
|
||||
import qualified Data.Aeson as JSON
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.Set as S
|
||||
import qualified Hasql.Decoders as HD
|
||||
import qualified Hasql.Encoders as HE
|
||||
import qualified Hasql.Statement as SQL
|
||||
import qualified Hasql.Transaction as SQL
|
||||
import qualified Data.Aeson as JSON
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.HashMap.Strict.InsOrd as HMI
|
||||
import qualified Data.Set as S
|
||||
import qualified Hasql.Decoders as HD
|
||||
import qualified Hasql.Encoders as HE
|
||||
import qualified Hasql.Statement as SQL
|
||||
import qualified Hasql.Transaction as SQL
|
||||
|
||||
import Contravariant.Extras (contrazip2)
|
||||
import Text.InterpolatedString.Perl6 (q)
|
||||
@@ -52,8 +53,8 @@ import PostgREST.SchemaCache.Relationship (Cardinality (..),
|
||||
Junction (..),
|
||||
Relationship (..),
|
||||
RelationshipsMap)
|
||||
import PostgREST.SchemaCache.Table (Column (..), Table (..),
|
||||
TablesMap)
|
||||
import PostgREST.SchemaCache.Table (Column (..), ColumnMap,
|
||||
Table (..), TablesMap)
|
||||
|
||||
import Protolude
|
||||
|
||||
@@ -178,15 +179,20 @@ decodeTables =
|
||||
<*> column HD.bool
|
||||
<*> column HD.bool
|
||||
<*> arrayColumn HD.text
|
||||
<*> compositeArrayColumn
|
||||
(Column
|
||||
<*> parseCols (compositeArrayColumn
|
||||
(Column
|
||||
<$> compositeField HD.text
|
||||
<*> nullableCompositeField HD.text
|
||||
<*> compositeField HD.bool
|
||||
<*> compositeField HD.text
|
||||
<*> compositeField HD.text
|
||||
<*> nullableCompositeField HD.int4
|
||||
<*> nullableCompositeField HD.text
|
||||
<*> compositeFieldArray HD.text)
|
||||
<*> compositeFieldArray HD.text))
|
||||
|
||||
|
||||
parseCols :: HD.Row [Column] -> HD.Row ColumnMap
|
||||
parseCols = fmap (HMI.fromList . map (\col@Column{colName} -> (colName, col)))
|
||||
|
||||
decodeRels :: HD.Result [Relationship]
|
||||
decodeRels =
|
||||
@@ -521,6 +527,7 @@ tablesSqlQuery pgVer =
|
||||
ELSE format_type(a.atttypid, a.atttypmod)
|
||||
END
|
||||
END::text AS data_type,
|
||||
t.oid AS data_type_id,
|
||||
information_schema._pg_char_max_length(
|
||||
information_schema._pg_truetypid(a.*, t.*),
|
||||
information_schema._pg_truetypmod(a.*, t.*)
|
||||
@@ -556,6 +563,7 @@ tablesSqlQuery pgVer =
|
||||
info.description,
|
||||
info.is_nullable::boolean,
|
||||
info.data_type,
|
||||
info.data_type_id::regtype::text,
|
||||
info.character_maximum_length,
|
||||
info.column_default,
|
||||
coalesce(enum_info.vals, '{}')) order by info.position) as columns
|
||||
|
||||
Reference in New Issue
Block a user