Skip to content

Commit 1c38e4a

Browse files
committed
Added basic support for Point types in DataSync
1 parent df18327 commit 1c38e4a

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

IHP/DataSync/DynamicQuery.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ data DynamicValue
2626
| BoolValue !Bool
2727
| UUIDValue !UUID
2828
| DateTimeValue !UTCTime
29+
| PointValue !Point
2930
| Null
3031
deriving (Show, Eq)
3132

@@ -84,6 +85,7 @@ instance {-# OVERLAPS #-} ToJSON [Field] where
8485
fieldValueToJSON (BoolValue value) = toJSON value
8586
fieldValueToJSON (UUIDValue value) = toJSON value
8687
fieldValueToJSON (DateTimeValue value) = toJSON value
88+
fieldValueToJSON (PointValue value) = toJSON value
8789
fieldValueToJSON IHP.DataSync.DynamicQuery.Null = toJSON Data.Aeson.Null
8890

8991
instance PG.FromField Field where
@@ -101,6 +103,7 @@ instance PG.FromField Field where
101103
<|> (UUIDValue <$> PG.fromField field fieldValue')
102104
<|> (DoubleValue <$> PG.fromField field fieldValue')
103105
<|> (DateTimeValue <$> PG.fromField field fieldValue')
106+
<|> (PointValue <$> PG.fromField field fieldValue')
104107
<|> (PG.fromField @PG.Null field fieldValue' >> pure IHP.DataSync.DynamicQuery.Null)
105108
<|> fromFieldCustomEnum field fieldValue'
106109

IHP/DataSync/DynamicQueryCompiler.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ compileCondition (LiteralExpression literal) = ("?", [toValue literal])
8282
toValue (BoolValue bool) = PG.toField bool
8383
toValue (UUIDValue uuid) = PG.toField uuid
8484
toValue (DateTimeValue utcTime) = PG.toField utcTime
85+
toValue (PointValue point) = PG.toField point
8586
toValue Null = PG.toField PG.Null
8687

8788
compileOperator :: ConditionOperator -> PG.Query

IHP/DataSync/REST/Controller.hs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,4 +198,22 @@ aesonValueToPostgresValue (Number value) = case Scientific.floatingOrInteger val
198198
Left (floating :: Double) -> PG.toField floating
199199
Right (integer :: Integer) -> PG.toField integer
200200
aesonValueToPostgresValue Data.Aeson.Null = PG.toField PG.Null
201-
aesonValueToPostgresValue object@(Object values) = PG.toField (toJSON object)
201+
aesonValueToPostgresValue object@(Object values) =
202+
let
203+
tryDecodeAsPoint :: Maybe Point
204+
tryDecodeAsPoint = do
205+
xValue <- HashMap.lookup "x" values
206+
yValue <- HashMap.lookup "y" values
207+
x <- case xValue of
208+
Number number -> pure (Scientific.toRealFloat number)
209+
otherwise -> Nothing
210+
y <- case yValue of
211+
Number number -> pure (Scientific.toRealFloat number)
212+
otherwise -> Nothing
213+
pure Point { x, y }
214+
in
215+
-- This is really hacky and is mostly duck typing. We should refactor this in the future to
216+
-- become more type aware by passing the DDL of the table to 'aesonValueToPostgresValue'.
217+
if HashMap.size values == 2
218+
then fromMaybe (PG.toField $ toJSON object) (PG.toField <$> tryDecodeAsPoint)
219+
else PG.toField (toJSON object)

IHP/Postgres/Point.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Database.PostgreSQL.Simple.TypeInfo.Macro as TI
1616
import Data.ByteString.Builder (byteString, char8)
1717
import Data.Attoparsec.ByteString.Char8 hiding (Result, char8, Parser(..))
1818
import Data.Attoparsec.Internal.Types (Parser)
19+
import Data.Aeson
1920

2021
-- | Represents a Postgres Point
2122
--
@@ -59,3 +60,12 @@ serializePoint Point { x, y } = Many
5960
, toField y
6061
, Plain (char8 ')')
6162
]
63+
64+
65+
instance FromJSON Point where
66+
parseJSON = withObject "Point" $ \v -> Point
67+
<$> v .: "x"
68+
<*> v .: "y"
69+
70+
instance ToJSON Point where
71+
toJSON Point { x, y } = object [ "x" .= x, "y" .= y ]

0 commit comments

Comments
 (0)