0 | module Postgres.Data.PostgresValue
6 | import Postgres.Data.PostgresType
10 | data PValue : (p : PType) -> Type where
11 | Raw : (rawString : String) -> PValue p
14 | Semigroup (PValue p) where
15 | (Raw x) <+> (Raw y) = Raw (x <+> y)
18 | Monoid (PValue p) where
22 | rawString : PValue t -> String
23 | rawString (Raw r) = r
30 | interface IdrCast pt ty where
31 | toIdris : PValue pt -> Maybe ty
34 | interface PGCast pt ty where
35 | toPostgres : ty -> PValue pt
40 | IdrCast PInteger Int where
41 | toIdris = parseInteger . rawString
44 | PGCast PInteger Int where
45 | toPostgres = Raw . show
48 | IdrCast PInteger Integer where
49 | toIdris = parseInteger . rawString
52 | PGCast PInteger Integer where
53 | toPostgres = Raw . show
56 | IdrCast PInteger Double where
57 | toIdris = parseDouble . rawString
60 | PGCast PInteger Nat where
61 | toPostgres = Raw . show
66 | IdrCast PDouble Double where
67 | toIdris = parseDouble . rawString
70 | PGCast PDouble Double where
71 | toPostgres = Raw . show
74 | PGCast PDouble Integer where
75 | toPostgres = Raw . show
78 | PGCast PDouble Int where
79 | toPostgres = Raw . show
84 | IdrCast PChar Char where
85 | toIdris (Raw str) with (unpack str)
86 | toIdris (Raw str) | [c] = Just c
87 | toIdris (Raw str) | _ = Nothing
90 | PGCast PChar Char where
91 | toPostgres c = Raw $
"'\{String.singleton c}'"
96 | IdrCast PBoolean Bool where
97 | toIdris (Raw "t") = Just True
98 | toIdris (Raw "f") = Just False
99 | toIdris (Raw "true") = Just True
100 | toIdris (Raw "false") = Just False
101 | toIdris (Raw "1") = Just True
102 | toIdris (Raw "0") = Just False
103 | toIdris (Raw _) = Nothing
106 | PGCast PBoolean Bool where
107 | toPostgres True = Raw "true"
108 | toPostgres False = Raw "false"
119 | Cast (PValue PString) String where
123 | IdrCast PString String where
124 | toIdris = Just . cast
127 | PGCast PString String where
128 | toPostgres s = Raw $
"'\{s}'"
133 | IdrCast PJson JSON where
135 | eitherToMaybe $
parseJSON Virtual (rawString json)
138 | PGCast PJson JSON where
139 | toPostgres j = Raw $
"'\{show j}'"
146 | IdrCast POid Integer where
147 | toIdris = parseInteger . rawString
150 | PGCast POid Integer where
151 | toPostgres = Raw . show
155 | parseArray : String -> Maybe (List String)
157 | let stripped = trim str
159 | do guard (("{" `isPrefixOf` stripped) && ("}" `isSuffixOf` stripped))
160 | let middle = reverse . (drop 1) . reverse . (drop 1) $
unpack stripped
161 | pure . forget $
pack <$> (splitOn ',' middle)
164 | IdrCast from to => IdrCast (PArray from) (List to) where
165 | toIdris (Raw rawString) = (parseArray rawString) >>= (traverse (toIdris . (Raw {p=from})))
168 | PGCast to from => PGCast (PArray to) (List from) where
170 | let values = concat . intersperse "," $
escaped . toPostgres {pt=to} <$> xs
171 | in Raw $
"'{" ++ values ++ "}'"
173 | escaped : PValue t -> String
174 | escaped (Raw str) = if "'" `isPrefixOf` str
181 | PGCast to (Maybe from) => PGCast to from where
182 | toPostgres = toPostgres . Just
188 | getSafeCast : (t1 : PType) -> IdrCast t1 t2 => IdrCast t1 t2
189 | getSafeCast t1 @{safe} = safe
192 | interface DBStringCast a where
196 | dbCast : String -> Either String a
199 | DBStringCast Integer where
200 | dbCast str = maybeToEither "Failed to parse an integer from '\{str}'" . toIdris @{getSafeCast PInteger} $
Raw str
203 | DBStringCast Double where
204 | dbCast str = maybeToEither "Failed to parse a double from '\{str}'" . toIdris @{getSafeCast PDouble} $
Raw str
207 | DBStringCast Char where
208 | dbCast str = maybeToEither "Failed to parse a char from '\{str}'" . toIdris @{getSafeCast PChar} $
Raw str
211 | DBStringCast Bool where
212 | dbCast str = maybeToEither "Failed to parse a boolean from '\{str}'" . toIdris @{getSafeCast PBoolean} $
Raw str
215 | DBStringCast String where
216 | dbCast str = maybeToEither "Failed to parse a string from '\{str}'" . toIdris @{getSafeCast PString} $
Raw str
219 | DBStringCast JSON where
220 | dbCast str = maybeToEither "Failed to parse json from '\{str}'" . toIdris @{getSafeCast PJson} $
Raw str
223 | DBStringCast a => DBStringCast (List a) where
224 | dbCast str = traverse dbCast <=< maybeToEither "Failed to parse an array '\{str}'" $
parseArray str
227 | [IdrCastString] IdrCast pt ty => DBStringCast ty where
228 | dbCast str = maybeToEither "Failed to parse '\{str}' as expected type." . toIdris {pt} $
Raw str
231 | data Castable : Type -> Type where
232 | Cast : DBStringCast ty => Castable ty
233 | CastMaybe : DBStringCast ty => Castable (Maybe ty)
240 | asDefaultType : Castable t -> (columnValue : Maybe String) -> Either String t
241 | asDefaultType (Cast @{dbcast}) = dbCast <=< maybeToEither "Unexpected null while casting Postgres values!"
242 | asDefaultType (CastMaybe @{dbcast}) = traverse dbCast