Read only proc tx (#844)
This commit is contained in:
@@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- #777, Empty body is allowed when calling a non-parameterized RPC - @koulakis
|
- #777, Empty body is allowed when calling a non-parameterized RPC - @koulakis
|
||||||
- #831, Fix proc resource embedding issue with search_path - @steve-chavez
|
- #831, Fix proc resource embedding issue with search_path - @steve-chavez
|
||||||
- #857, Fix swagger-ui when "server-proxy-uri" is not set - @feynmanliang
|
- #857, Fix swagger-ui when "server-proxy-uri" is not set - @feynmanliang
|
||||||
|
- #547, Use read-only transaction for stable/immutable RPC - @begriffs
|
||||||
|
|
||||||
## [0.4.0.0] - 2017-01-19
|
## [0.4.0.0] - 2017-01-19
|
||||||
|
|
||||||
|
|||||||
+19
-5
@@ -79,15 +79,29 @@ postgrest conf refDbStructure pool getTime =
|
|||||||
eClaims = jwtClaims jwtSecret (iJWT apiRequest) time
|
eClaims = jwtClaims jwtSecret (iJWT apiRequest) time
|
||||||
authed = containsRole eClaims
|
authed = containsRole eClaims
|
||||||
handleReq = runWithClaims conf eClaims (app dbStructure conf) apiRequest
|
handleReq = runWithClaims conf eClaims (app dbStructure conf) apiRequest
|
||||||
txMode = transactionMode $ iAction apiRequest
|
txMode = transactionMode dbStructure
|
||||||
|
(iTarget apiRequest) (iAction apiRequest)
|
||||||
response <- P.use pool $ HT.transaction HT.ReadCommitted txMode handleReq
|
response <- P.use pool $ HT.transaction HT.ReadCommitted txMode handleReq
|
||||||
return $ either (pgError authed) identity response
|
return $ either (pgError authed) identity response
|
||||||
respond response
|
respond response
|
||||||
|
|
||||||
transactionMode :: Action -> H.Mode
|
transactionMode :: DbStructure -> Target -> Action -> H.Mode
|
||||||
transactionMode ActionRead = HT.Read
|
transactionMode structure target action =
|
||||||
transactionMode ActionInfo = HT.Read
|
case action of
|
||||||
transactionMode _ = HT.Write
|
ActionRead -> HT.Read
|
||||||
|
ActionInfo -> HT.Read
|
||||||
|
ActionInspect -> HT.Read
|
||||||
|
ActionInvoke ->
|
||||||
|
let proc =
|
||||||
|
case target of
|
||||||
|
(TargetProc qi) -> M.lookup (qiName qi) $
|
||||||
|
dbProcs structure
|
||||||
|
_ -> Nothing
|
||||||
|
v = fromMaybe Volatile $ pdVolatility <$> proc in
|
||||||
|
if v == Stable || v == Immutable
|
||||||
|
then HT.Read
|
||||||
|
else HT.Write
|
||||||
|
_ -> HT.Write
|
||||||
|
|
||||||
app :: DbStructure -> AppConfig -> ApiRequest -> H.Transaction Response
|
app :: DbStructure -> AppConfig -> ApiRequest -> H.Transaction Response
|
||||||
app dbStructure conf apiRequest =
|
app dbStructure conf apiRequest =
|
||||||
|
|||||||
@@ -100,10 +100,19 @@ decodeSynonyms cols =
|
|||||||
accessibleProcs :: H.Query Schema (M.HashMap Text ProcDescription)
|
accessibleProcs :: H.Query Schema (M.HashMap Text ProcDescription)
|
||||||
accessibleProcs =
|
accessibleProcs =
|
||||||
H.statement sql (HE.value HE.text)
|
H.statement sql (HE.value HE.text)
|
||||||
(M.fromList . map addName <$> HD.rowsList (ProcDescription <$> HD.value HD.text
|
(M.fromList . map addName <$>
|
||||||
<*> (parseArgs <$> HD.value HD.text)
|
HD.rowsList (
|
||||||
<*> (parseRetType <$> HD.value HD.text <*> HD.value HD.text <*>
|
ProcDescription <$> HD.value HD.text
|
||||||
HD.value HD.bool <*> HD.value HD.char))) True
|
<*> (parseArgs <$> HD.value HD.text)
|
||||||
|
<*> (parseRetType <$>
|
||||||
|
HD.value HD.text <*>
|
||||||
|
HD.value HD.text <*>
|
||||||
|
HD.value HD.bool <*>
|
||||||
|
HD.value HD.char)
|
||||||
|
<*> (parseVolatility <$>
|
||||||
|
HD.value HD.char)
|
||||||
|
)
|
||||||
|
) True
|
||||||
where
|
where
|
||||||
addName :: ProcDescription -> (Text, ProcDescription)
|
addName :: ProcDescription -> (Text, ProcDescription)
|
||||||
addName pd = (pdName pd, pd)
|
addName pd = (pdName pd, pd)
|
||||||
@@ -131,13 +140,20 @@ accessibleProcs =
|
|||||||
'p' -> Pseudo name
|
'p' -> Pseudo name
|
||||||
_ -> Scalar qi -- 'b'ase, 'd'omain, 'e'num, 'r'ange
|
_ -> Scalar qi -- 'b'ase, 'd'omain, 'e'num, 'r'ange
|
||||||
|
|
||||||
|
parseVolatility :: Char -> ProcVolatility
|
||||||
|
parseVolatility 'i' = Immutable
|
||||||
|
parseVolatility 's' = Stable
|
||||||
|
parseVolatility 'v' = Volatile
|
||||||
|
parseVolatility _ = Volatile -- should not happen, but be pessimistic
|
||||||
|
|
||||||
sql = [q|
|
sql = [q|
|
||||||
SELECT p.proname as "proc_name",
|
SELECT p.proname as "proc_name",
|
||||||
pg_get_function_arguments(p.oid) as "args",
|
pg_get_function_arguments(p.oid) as "args",
|
||||||
tn.nspname as "rettype_schema",
|
tn.nspname as "rettype_schema",
|
||||||
coalesce(comp.relname, t.typname) as "rettype_name",
|
coalesce(comp.relname, t.typname) as "rettype_name",
|
||||||
p.proretset as "rettype_is_setof",
|
p.proretset as "rettype_is_setof",
|
||||||
t.typtype as "rettype_typ"
|
t.typtype as "rettype_typ",
|
||||||
|
p.provolatile
|
||||||
FROM pg_proc p
|
FROM pg_proc p
|
||||||
JOIN pg_namespace pn ON pn.oid = p.pronamespace
|
JOIN pg_namespace pn ON pn.oid = p.pronamespace
|
||||||
JOIN pg_type t ON t.oid = p.prorettype
|
JOIN pg_type t ON t.oid = p.prorettype
|
||||||
|
|||||||
@@ -41,10 +41,14 @@ data PgType = Scalar QualifiedIdentifier | Composite QualifiedIdentifier | Pseud
|
|||||||
|
|
||||||
data RetType = Single PgType | SetOf PgType deriving (Eq, Show)
|
data RetType = Single PgType | SetOf PgType deriving (Eq, Show)
|
||||||
|
|
||||||
|
data ProcVolatility = Volatile | Stable | Immutable
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
data ProcDescription = ProcDescription {
|
data ProcDescription = ProcDescription {
|
||||||
pdName :: Text
|
pdName :: Text
|
||||||
, pdArgs :: [PgArg]
|
, pdArgs :: [PgArg]
|
||||||
, pdReturnType :: RetType
|
, pdReturnType :: RetType
|
||||||
|
, pdVolatility :: ProcVolatility
|
||||||
} deriving (Show, Eq)
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
type Schema = Text
|
type Schema = Text
|
||||||
|
|||||||
Vendored
+1
@@ -316,6 +316,7 @@ $$;
|
|||||||
|
|
||||||
CREATE FUNCTION sayhello(name text) RETURNS text
|
CREATE FUNCTION sayhello(name text) RETURNS text
|
||||||
LANGUAGE sql
|
LANGUAGE sql
|
||||||
|
IMMUTABLE
|
||||||
AS $_$
|
AS $_$
|
||||||
SELECT 'Hello, ' || $1;
|
SELECT 'Hello, ' || $1;
|
||||||
$_$;
|
$_$;
|
||||||
|
|||||||
Reference in New Issue
Block a user