good morning!!!!

Skip to content
Snippets Groups Projects
eq.go 2.08 KiB
Newer Older
Garet Halliday's avatar
Garet Halliday committed
package gsql
Garet Halliday's avatar
Garet Halliday committed

import (
Garet Halliday's avatar
a  
Garet Halliday committed
	"reflect"
Garet Halliday's avatar
Garet Halliday committed
	"strconv"
Garet Halliday's avatar
Garet Halliday committed
	"gfx.cafe/gfx/pggat/lib/fed"
	packets "gfx.cafe/gfx/pggat/lib/fed/packets/v3.0"
func ExtendedQuery(client *fed.Conn, result any, query string, args ...any) error {
Garet Halliday's avatar
Garet Halliday committed
	if len(args) == 0 {
		return Query(client, []any{result}, query)
Garet Halliday's avatar
Garet Halliday committed
	}

	// parse
	parse := packets.Parse{
		Query: query,
	}
	if err := client.WritePacket(&parse); err != nil {
		return err
	}
Garet Halliday's avatar
Garet Halliday committed

	// bind
	params := make([][]byte, 0, len(args))
Garet Halliday's avatar
Garet Halliday committed
outer:
Garet Halliday's avatar
Garet Halliday committed
	for _, arg := range args {
		var value []byte
Garet Halliday's avatar
Garet Halliday committed
		argr := reflect.ValueOf(arg)
		for argr.Kind() == reflect.Pointer {
			if argr.IsNil() {
				params = append(params, nil)
				continue outer
			}
			argr = argr.Elem()
		}
		switch argr.Kind() {
		case reflect.String:
			value = []byte(argr.String())
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			value = []byte(strconv.FormatUint(argr.Uint(), 10))
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			value = []byte(strconv.FormatInt(argr.Int(), 10))
		case reflect.Float32, reflect.Float64:
			value = []byte(strconv.FormatFloat(argr.Float(), 'f', -1, 64))
		case reflect.Bool:
			if argr.Bool() {
				value = []byte{'t'}
			} else {
				value = []byte{'f'}
			}
Garet Halliday's avatar
Garet Halliday committed
		case reflect.Invalid:
			value = nil
Garet Halliday's avatar
Garet Halliday committed
		default:
			return ErrUnexpectedType
		}
		params = append(params, value)
	}
	bind := packets.Bind{
Garet Halliday's avatar
Garet Halliday committed
		Parameters: params,
Garet Halliday's avatar
Garet Halliday committed
	}
	if err := client.WritePacket(&bind); err != nil {
		return err
	}
Garet Halliday's avatar
Garet Halliday committed

	// describe
	describe := packets.Describe{
		Which: 'P',
	}
	if err := client.WritePacket(&describe); err != nil {
		return err
	}
Garet Halliday's avatar
Garet Halliday committed

	// execute
Garet Halliday's avatar
Garet Halliday committed
	execute := packets.Execute{}
	if err := client.WritePacket(&execute); err != nil {
		return err
	}
Garet Halliday's avatar
Garet Halliday committed
	// sync
Garet Halliday's avatar
Garet Halliday committed
	sync := packets.Sync{}
	if err := client.WritePacket(&sync); err != nil {
		return err
	}
Garet Halliday's avatar
Garet Halliday committed
	// result
	if err := readQueryResults(client, result); err != nil {
		return err
	}

	// make sure we receive ready for query
	packet, err := client.ReadPacket(true)
	if err != nil {
		return err
	}

	if packet.Type() != packets.TypeReadyForQuery {
		return ErrExpectedReadyForQuery
	}

Garet Halliday's avatar
Garet Halliday committed
	return nil
}