good morning!!!!

Skip to content
Snippets Groups Projects
Commit 1b1d1a53 authored by Garet Halliday's avatar Garet Halliday
Browse files

daisy chained gats pass tests

fixes #6
parent ff4af9eb
No related branches found
No related tags found
No related merge requests found
...@@ -192,10 +192,10 @@ func (T *State) ReadyForQuery(packet fed.Packet) { ...@@ -192,10 +192,10 @@ func (T *State) ReadyForQuery(packet fed.Packet) {
} }
// all pending has failed // all pending has failed
for _, ok := T.pendingPreparedStatements.PopBack(); ok; _, ok = T.pendingPortals.PopBack() { for _, ok := T.pendingPreparedStatements.PopBack(); ok; _, ok = T.pendingPreparedStatements.PopBack() {
} }
for _, ok := T.pendingPortals.PopBack(); ok; _, ok = T.pendingPortals.PopBack() { for _, ok := T.pendingPortals.PopBack(); ok; _, ok = T.pendingPortals.PopBack() {
} }
for _, ok := T.pendingCloses.PopBack(); ok; _, ok = T.pendingPortals.PopBack() { for _, ok := T.pendingCloses.PopBack(); ok; _, ok = T.pendingCloses.PopBack() {
} }
} }
...@@ -22,12 +22,18 @@ func Sync(c *Client, server fed.ReadWriter, s *Server) error { ...@@ -22,12 +22,18 @@ func Sync(c *Client, server fed.ReadWriter, s *Server) error {
// close all prepared statements that don't match client // close all prepared statements that don't match client
for name, preparedStatement := range s.state.preparedStatements { for name, preparedStatement := range s.state.preparedStatements {
clientPreparedStatement, ok := c.state.preparedStatements[name] if clientPreparedStatement, ok := c.state.preparedStatements[name]; ok {
if ok && (name == "" || preparedStatement.Hash == clientPreparedStatement.Hash) { if preparedStatement.Hash == clientPreparedStatement.Hash {
// match or unnamed prepared statement that will be bound over // the same
continue continue
} }
if name == "" {
// will be overwritten
continue
}
}
p := packets.Close{ p := packets.Close{
Which: 'S', Which: 'S',
Target: name, Target: name,
...@@ -39,11 +45,12 @@ func Sync(c *Client, server fed.ReadWriter, s *Server) error { ...@@ -39,11 +45,12 @@ func Sync(c *Client, server fed.ReadWriter, s *Server) error {
// parse all prepared statements that aren't on server // parse all prepared statements that aren't on server
for name, preparedStatement := range c.state.preparedStatements { for name, preparedStatement := range c.state.preparedStatements {
serverPreparedStatement, ok := s.state.preparedStatements[name] if serverPreparedStatement, ok := s.state.preparedStatements[name]; ok {
if ok && preparedStatement.Hash == serverPreparedStatement.Hash { if preparedStatement.Hash == serverPreparedStatement.Hash {
// matched, don't need to set // the same
continue continue
} }
}
if err := server.WritePacket(preparedStatement.Packet); err != nil { if err := server.WritePacket(preparedStatement.Packet); err != nil {
return err return err
......
package ring package ring
type Ring[T any] struct { type Ring[T any] struct {
buffer []T buf []T
// real head is head-1, like this so nil ring is valid
head int head int
tail int tail int
length int length int
...@@ -9,128 +10,138 @@ type Ring[T any] struct { ...@@ -9,128 +10,138 @@ type Ring[T any] struct {
func MakeRing[T any](length, capacity int) Ring[T] { func MakeRing[T any](length, capacity int) Ring[T] {
if length > capacity { if length > capacity {
// programmer error, panic panic("length must be less than capacity")
panic("length must be < capacity")
}
if capacity < 0 {
panic("capacity must be >= 0")
}
tail := length + 1
if tail >= capacity {
tail -= capacity
} }
return Ring[T]{ return Ring[T]{
buffer: make([]T, capacity), buf: make([]T, capacity),
head: 0, tail: length,
length: length, length: length,
tail: tail,
} }
} }
func NewRing[T any](length, capacity int) *Ring[T] { func NewRing[T any](length, capacity int) *Ring[T] {
ring := MakeRing[T](length, capacity) r := MakeRing[T](length, capacity)
return &ring return &r
} }
func (r *Ring[T]) grow() { func (r *Ring[T]) grow() {
if cap(r.buffer) == 0 { size := len(r.buf) * 2
// special case, uninitialized if size == 0 {
r.buffer = make([]T, 2) size = 2
r.head = 0
r.tail = 1
return
} }
// make new buffer with twice as much space buf := make([]T, size)
buf := make([]T, cap(r.buffer)*2) copy(buf, r.buf[r.head:])
copy(buf[len(r.buf[r.head:]):], r.buf[:r.head])
r.head = 0
r.tail = r.length
r.buf = buf
}
// copy from [head, end of buffer] into new buffer func (r *Ring[T]) incHead() {
copy(buf, r.buffer[r.head:]) // resize
// copy from [beginning of buffer, tail) into new buffer if r.length == 0 {
copy(buf[len(r.buffer)-r.head:], r.buffer[:r.tail]) panic("smashing detected")
}
r.length--
r.tail = len(r.buffer) - r.head + r.tail r.head++
if r.head == len(r.buf) {
r.head = 0 r.head = 0
r.buffer = buf
} }
func (r *Ring[T]) PushBack(value T) {
if r == nil {
panic("PushBack() on nil Ring")
} }
if r.length == cap(r.buffer) {
func (r *Ring[T]) decHead() {
// resize
if r.length == len(r.buf) {
r.grow() r.grow()
} }
r.buffer[r.tail] = value
r.tail++
if r.tail >= len(r.buffer) {
r.tail -= len(r.buffer)
}
r.length++ r.length++
}
func (r *Ring[T]) PushFront(value T) { r.head--
if r == nil { if r.head == -1 {
panic("PushFront() on nil Ring") r.head = len(r.buf) - 1
} }
if r.length == cap(r.buffer) {
r.grow()
} }
r.buffer[r.head] = value
r.head-- func (r *Ring[T]) incTail() {
if r.head < 0 { // resize
r.head += len(r.buffer) if r.length == len(r.buf) {
r.grow()
} }
r.length++ r.length++
r.tail++
if r.tail == len(r.buf) {
r.tail = 0
}
} }
func (r *Ring[T]) PopBack() (T, bool) { func (r *Ring[T]) decTail() {
if r == nil || r.length == 0 { // resize
return *new(T), false if r.length == 0 {
panic("smashing detected")
}
r.length--
r.tail--
if r.tail == -1 {
r.tail = len(r.buf) - 1
}
} }
func (r *Ring[T]) tailSub1() int {
tail := r.tail - 1 tail := r.tail - 1
if tail < 0 { if tail == -1 {
tail += len(r.buffer) tail = len(r.buf) - 1
} }
r.tail = tail return tail
r.length--
return r.buffer[tail], true
} }
func (r *Ring[T]) PopFront() (T, bool) { func (r *Ring[T]) PopFront() (T, bool) {
if r == nil || r.length == 0 { if r.length == 0 {
return *new(T), false return *new(T), false
} }
head := r.head + 1
if head >= len(r.buffer) { front := r.buf[r.head]
head -= len(r.buffer) r.incHead()
} return front, true
r.head = head
r.length--
return r.buffer[head], true
} }
func (r *Ring[T]) Get(i int) (T, bool) { func (r *Ring[T]) PopBack() (T, bool) {
if r == nil || i >= r.length || i < 0 { if r.length == 0 {
return *new(T), false return *new(T), false
} }
ptr := r.head + 1 + i
if ptr >= len(r.buffer) { r.decTail()
ptr -= len(r.buffer) return r.buf[r.tail], true
} }
return r.buffer[ptr], true
func (r *Ring[T]) PushFront(value T) {
r.decHead()
r.buf[r.head] = value
} }
func (r *Ring[T]) Length() int { func (r *Ring[T]) PushBack(value T) {
if r == nil { r.incTail()
return 0 r.buf[r.tailSub1()] = value
} }
func (r *Ring[T]) Length() int {
return r.length return r.length
} }
func (r *Ring[T]) Capacity() int { func (r *Ring[T]) Capacity() int {
if r == nil { return len(r.buf)
return 0 }
func (r *Ring[T]) Get(n int) T {
if n >= r.length {
panic("index out of range")
}
ptr := r.head + n
if ptr >= len(r.buf) {
ptr -= len(r.buf)
} }
return cap(r.buffer) return r.buf[ptr]
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment