Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions async_postgres/pg_types/encoding.nim
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ template writeBE64*(buf: var openArray[byte], pos: int, v: int64) =
buf[pos + 6] = byte((v shr 8) and 0xFF)
buf[pos + 7] = byte(v and 0xFF)

template writeBytesAt*(dst: var openArray[byte], pos: int, src: openArray[byte]) =
## Copy src bytes into dst starting at pos. No-op when src is empty.
if src.len > 0:
copyMem(addr dst[pos], addr src[0], src.len)

proc toPgParamInline*(v: int16): PgParamInline =
result.oid = OidInt2
result.format = 1
Expand Down Expand Up @@ -276,9 +281,8 @@ proc encodeBinaryArray*(elemOid: int32, elements: seq[seq[byte]]): seq[byte] =
for e in elements:
result.writeBE32(pos, int32(e.len))
pos += 4
if e.len > 0:
copyMem(addr result[pos], addr e[0], e.len)
pos += e.len
result.writeBytesAt(pos, e)
pos += e.len

proc encodeBinaryArray*(elemOid: int32, elements: seq[Option[seq[byte]]]): seq[byte] =
## Encode a 1-dimensional binary array that may contain NULL elements.
Expand Down Expand Up @@ -315,9 +319,8 @@ proc encodeBinaryArray*(elemOid: int32, elements: seq[Option[seq[byte]]]): seq[b
let ev = e.get
result.writeBE32(pos, int32(ev.len))
pos += 4
if ev.len > 0:
copyMem(addr result[pos], addr ev[0], ev.len)
pos += ev.len
result.writeBytesAt(pos, ev)
pos += ev.len

proc encodeBinaryArrayEmpty*(elemOid: int32): seq[byte] =
## Encode an empty 1-dimensional PostgreSQL binary array.
Expand Down Expand Up @@ -975,14 +978,15 @@ proc encodeHstoreBinary*(v: PgHstore): seq[byte] =
result.writeBE32(pos, int32(k.len))
pos += 4
if k.len > 0:
copyMem(addr result[pos], addr k[0], k.len)
result.writeBytesAt(pos, k.toOpenArrayByte(0, k.high))
pos += k.len
if val.isSome:
result.writeBE32(pos, int32(val.get.len))
let vs = val.get
result.writeBE32(pos, int32(vs.len))
pos += 4
if val.get.len > 0:
copyMem(addr result[pos], addr val.get[0], val.get.len)
pos += val.get.len
if vs.len > 0:
result.writeBytesAt(pos, vs.toOpenArrayByte(0, vs.high))
pos += vs.len
else:
result.writeBE32(pos, -1'i32)
pos += 4
Expand Down
25 changes: 9 additions & 16 deletions async_postgres/pg_types/ranges.nim
Original file line number Diff line number Diff line change
Expand Up @@ -338,18 +338,14 @@ proc encodeRangeBinaryImpl(r: RangeBinaryInput): seq[byte] =
result[0] = flags
var pos = 1
if r.hasLower:
let lb = toBE32(int32(r.lowerData.len))
copyMem(addr result[pos], addr lb[0], 4)
result.writeBE32(pos, int32(r.lowerData.len))
pos += 4
if r.lowerData.len > 0:
copyMem(addr result[pos], addr r.lowerData[0], r.lowerData.len)
pos += r.lowerData.len
result.writeBytesAt(pos, r.lowerData)
pos += r.lowerData.len
if r.hasUpper:
let ub = toBE32(int32(r.upperData.len))
copyMem(addr result[pos], addr ub[0], 4)
result.writeBE32(pos, int32(r.upperData.len))
pos += 4
if r.upperData.len > 0:
copyMem(addr result[pos], addr r.upperData[0], r.upperData.len)
result.writeBytesAt(pos, r.upperData)

# toPgParam for range types (text format)

Expand Down Expand Up @@ -734,16 +730,13 @@ proc encodeMultirangeBinaryImpl(rangeData: seq[seq[byte]]): seq[byte] =
for rd in rangeData:
size += 4 + rd.len
result = newSeq[byte](size)
let cnt = toBE32(int32(rangeData.len))
copyMem(addr result[0], addr cnt[0], 4)
result.writeBE32(0, int32(rangeData.len))
var pos = 4
for rd in rangeData:
let rl = toBE32(int32(rd.len))
copyMem(addr result[pos], addr rl[0], 4)
result.writeBE32(pos, int32(rd.len))
pos += 4
if rd.len > 0:
copyMem(addr result[pos], addr rd[0], rd.len)
pos += rd.len
result.writeBytesAt(pos, rd)
pos += rd.len

# Multirange toPgParam (text format)

Expand Down
21 changes: 7 additions & 14 deletions async_postgres/pg_types/user_types.nim
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import std/[options, macros, strutils, typetraits]

import ../pg_protocol
import ./core
import ./decoding
import ./accessors
import core, decoding, encoding, accessors

# User-defined enum type support
#
Expand Down Expand Up @@ -262,25 +260,20 @@ proc encodeBinaryComposite*(
if f.data.isSome:
size += f.data.get.len
result = newSeq[byte](size)
let nf = toBE32(int32(fields.len))
copyMem(addr result[0], addr nf[0], 4)
result.writeBE32(0, int32(fields.len))
var pos = 4
for f in fields:
let oid = toBE32(f.oid)
copyMem(addr result[pos], addr oid[0], 4)
result.writeBE32(pos, f.oid)
pos += 4
if f.data.isNone:
let nl = toBE32(-1'i32)
copyMem(addr result[pos], addr nl[0], 4)
result.writeBE32(pos, -1'i32)
pos += 4
else:
let data = f.data.get
let dl = toBE32(int32(data.len))
copyMem(addr result[pos], addr dl[0], 4)
result.writeBE32(pos, int32(data.len))
pos += 4
if data.len > 0:
copyMem(addr result[pos], addr data[0], data.len)
pos += data.len
result.writeBytesAt(pos, data)
pos += data.len

proc compositeFieldToText(val: string): string =
## Escape a composite field value for text format output.
Expand Down