8000 Encoding/Decoding NULL values as empty strings · postgres-haskell/postgres-wire@d12619c · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit d12619c

Browse files
Encoding/Decoding NULL values as empty strings
1 parent 45c3e25 commit d12619c

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

src/Database/PostgreSQL/Protocol/Decoders.hs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ decodeServerMessage = do
5151
>>= decodeCommandResult)
5252
'D' -> do
5353
columnCount <- fromIntegral <$> getInt16be
54-
DataRow <$> V.replicateM columnCount
55-
(getInt32be >>= getByteString . fromIntegral)
54+
DataRow <$> V.replicateM columnCount decodeValue
5655
'I' -> pure EmptyQueryResponse
5756
'E' -> ErrorResponse <$>
5857
(getByteString (fromIntegral $ len - 4) >>= decodeErrorDesc)
@@ -72,6 +71,12 @@ decodeServerMessage = do
7271
rowsCount <- fromIntegral <$> getInt16be
7372
RowDescription <$> V.replicateM rowsCount decodeFieldDescription
7473

74+
-- | Decodes a single data value. Length `-1` indicates a NULL column value.
75+
-- No value bytes follow in the NULL case.
76+
decodeValue :: Get B.ByteString
77+
decodeValue = fromIntegral <$> getInt32be >>= \n ->
78+
if n == -1 then pure "" else getByteString n
79+
7580
decodeTransactionStatus :: Get TransactionStatus
7681
decodeTransactionStatus = getWord8 >>= \t ->
7782
case chr $ fromIntegral t of

src/Database/PostgreSQL/Protocol/Encoders.hs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ encodeClientMessage (Bind (PortalName portalName) (StatementName stmtName)
3636
int16BE 1 <>
3737
encodeFormat paramFormat <>
3838
int16BE (fromIntegral $ V.length values) <>
39-
-- TODO - 8000 1 indicates a NULL parameter value. No value bytes
40-
-- follow in the NULL case.
41-
fold ((\v -> int32BE (fromIntegral $ B.length v) <> byteString v)
42-
<$> values) <>
39+
fold (encodeValue <$> values) <>
4340
-- `1` means that the specified format code is applied to all
4441
-- result columns (if any)
4542
int16BE 1 <>
@@ -76,6 +73,13 @@ encodeClientMessage Sync
7673
encodeClientMessage Terminate
7774
= prependHeader 'X' mempty
7875

76+
-- Encodes single data values. Length `-1` indicates a NULL parameter value.
77+
-- No value bytes follow in the NULL case.
78+
encodeValue :: B.ByteString -> Builder
79+
encodeValue v | B.null v = int32BE (-1)
80+
| otherwise = int32BE (fromIntegral $ B.length v)
81+
<> byteString v
82+
7983
encodeFormat :: Format -> Builder
8084
encodeFormat Text = int16BE 0
8185
encodeFormat Binary = int16BE 1

src/Database/PostgreSQL/Protocol/Types.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ data AuthResponse
102102
data ClientMessage
103103
= Bind PortalName StatementName
104104
Format -- parameter format code, one format for all
105-
(Vector ByteString) -- the values of parameters
105+
(Vector ByteString) -- the values of parameters, the empty string
106+
-- is recognized as NULL
106107
Format -- to apply code to all result columns
107108
-- Postgres use one command `close` for closing both statements and
108109
-- portals, but we distinguish them
@@ -130,7 +131,8 @@ data ServerMessage
130131
| BindComplete
131132
| CloseComplete
132133
| CommandComplete CommandResult
133-
| DataRow (Vector ByteString)
134+
| DataRow (Vector ByteString) -- an empty string should be recognized
135+
-- as NULL
134136
| EmptyQueryResponse
135137
| ErrorResponse ErrorDesc
136138
| NoData

0 commit comments

Comments
 (0)
0