0 | module Postgres.Query
2 | import public JSON.Parser
3 | import public Data.Vect.Quantifiers
4 | import public Postgres.Data.PostgresValue
6 | import Postgres.FFI.Utility
7 | import Postgres.Data.Conn
8 | import Postgres.Data.PostgresType
10 | import Postgres.Result
11 | import Decidable.Equality
21 | maybeFirstRowCol : {r,c : Nat} -> TupleResult r c -> Maybe String
22 | maybeFirstRowCol res = do row <- natToFin 0 r
24 | pure $
pgResultStringValue res row col
30 | headerNames : {colCount : Nat} -> TupleResult _ colCount -> Vect colCount String
31 | headerNames t = pgResultsetColNames t
33 | headerTypes : {auto types : TypeDictionary}
35 | -> TupleResult _ colCount
36 | -> Vect colCount PType
37 | headerTypes t = pgResultsetColTypes t
39 | headers : {auto types : TypeDictionary}
41 | -> TupleResult _ colCount
42 | -> Vect colCount ColHeader
43 | headers t = (uncurry MkHeader) <$> (zip (headerNames t) (headerTypes t))
49 | rows : {rowCount, colCount : Nat} -> TupleResult rowCount colCount -> Vect rowCount (Vect colCount (Maybe String))
50 | rows t = (map force) <$> pgNullableStringResultset t
53 | pgStringResultsQuery : {auto types : TypeDictionary}
57 | -> IO (Either String (StringResultset header))
58 | pgStringResultsQuery header query conn = withExecResult conn query stringResults
60 | stringResults : Result -> IO (Either String (StringResultset header))
61 | stringResults r = do Nothing <- pure $
pgResultErrorMessage r
62 | | Just err => pure $
Left err
63 | Just tuples <- pure $
tupleResult r
64 | | Nothing => pure $
Left "query did not result in expected response."
65 | pure $
Right $
if header
66 | then (
_ ** _ ** (headers tuples, rows tuples))
67 | else (
_ ** _ ** rows tuples)
76 | pgJSONResultQuery : (query: String) -> Conn -> IO (Maybe JSON)
77 | pgJSONResultQuery query conn = withExecResult conn query toJson where
78 | toJson : Result -> IO (Maybe JSON)
79 | toJson r = pure $
[ json | json <- eitherToMaybe $ parseJSON Virtual !(maybeFirstRowCol !(tupleResult r))
88 | processValue : Castable expectation
90 | -> Either String expectation
91 | processValue hasDefault = (asDefaultType hasDefault)
93 | processCols : {0 expected : Vect colCount Type}
94 | -> All Castable expected
95 | -> Vect colCount (Maybe String)
96 | -> Either String (HVect expected)
97 | processCols [] [] = Right []
98 | processCols (castable :: castables) (x :: xs) =
99 | [| (processValue castable x) :: (processCols castables xs) |]
101 | processRows : {0 expected : Vect colCount Type}
102 | -> {auto castable : (All Castable expected)}
103 | -> Vect rowCount (Vect colCount (Maybe String))
104 | -> Either String (Vect rowCount (HVect expected))
105 | processRows xs = traverse (processCols castable) xs
109 | pgResultQuery : {auto types : TypeDictionary}
110 | -> {colCount : Nat}
111 | -> (expected : Vect colCount Type)
112 | -> (query : String)
114 | -> {auto castable : (All Castable expected)}
115 | -> IO (Either String (
rowCount ** Vect rowCount (HVect expected))
)
116 | pgResultQuery expected query conn =
117 | do Right (
rowCount ** receivedCols ** strings)
<- pgStringResultsQuery False query conn
118 | | Left err => pure $
Left err
120 | case decEq colCount receivedCols of
122 | Left $
columnMismatchError receivedCols
123 | (Yes correctCols) =>
124 | (MkDPair rowCount) <$> processRows (rewrite correctCols in strings)
126 | columnMismatchError : (received : Nat) -> String
127 | columnMismatchError received =
128 | "Wrong number of columns returned. Expected " ++ (show colCount) ++ " but got " ++ (show received)