github.com/blong14/gache@v0.0.0-20240124023949-89416fd8bbfa/sql/conn.go (about)

     1  package sql
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"database/sql/driver"
     7  	"errors"
     8  	"fmt"
     9  	"io"
    10  	"strconv"
    11  	"strings"
    12  	"sync"
    13  
    14  	gdb "github.com/blong14/gache/internal/db"
    15  	glog "github.com/blong14/gache/internal/logging"
    16  	gproxy "github.com/blong14/gache/internal/proxy"
    17  )
    18  
    19  type QueryResponse struct {
    20  	Key         []byte
    21  	Value       []byte
    22  	RangeValues [][][]byte
    23  	Stats       gdb.QueryStats
    24  	Success     bool
    25  }
    26  
    27  type rows struct {
    28  	next *QueryResponse
    29  	done bool
    30  }
    31  
    32  func (r *rows) Columns() []string {
    33  	return []string{"value"}
    34  }
    35  
    36  func (r *rows) Close() error {
    37  	return nil
    38  }
    39  
    40  func (r *rows) Next(dest []driver.Value) error {
    41  	dest[0] = r.next
    42  	r.done = true
    43  	return nil
    44  }
    45  
    46  func (r *rows) HasNextResultSet() bool {
    47  	hasNext := r.next != nil && !r.done
    48  	return hasNext
    49  }
    50  
    51  func (r *rows) NextResultSet() error {
    52  	if r.next == nil {
    53  		return io.EOF
    54  	}
    55  	r.next = nil
    56  	return nil
    57  }
    58  
    59  type conn struct {
    60  	proxy *gproxy.QueryProxy
    61  }
    62  
    63  func (c *conn) Commit() error {
    64  	return errors.New("not implemented")
    65  }
    66  
    67  func (c *conn) Rollback() error {
    68  	return errors.New("not implemented")
    69  }
    70  
    71  func (c *conn) Prepare(_ string) (driver.Stmt, error) {
    72  	return nil, errors.New("not implemented")
    73  }
    74  
    75  func (c *conn) Close() error {
    76  	glog.Track("closing db connection...")
    77  	return nil
    78  }
    79  
    80  func (c *conn) Begin() (driver.Tx, error) {
    81  	return nil, errors.New("not implemented")
    82  }
    83  
    84  func (c *conn) Query(query string, args []driver.NamedValue) (driver.Rows, error) {
    85  	return c.QueryContext(context.Background(), query, args)
    86  }
    87  
    88  func (c *conn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
    89  	q, err := parse(strings.NewReader(query))
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	for _, arg := range args {
    94  		valueOrKey := arg.Value.([]byte)
    95  		switch arg.Name {
    96  		case "table":
    97  			q.Header.TableName = valueOrKey
    98  		case "start":
    99  			q.KeyRange.Start = valueOrKey
   100  		case "end":
   101  			q.KeyRange.End = valueOrKey
   102  		case "key":
   103  			q.Key = valueOrKey
   104  		case "value":
   105  			q.Value = valueOrKey
   106  		case "limit":
   107  			q.KeyRange.Limit, err = strconv.Atoi(string(valueOrKey))
   108  			if err != nil {
   109  				return nil, fmt.Errorf("invalid limit arg: %w", err)
   110  			}
   111  		default:
   112  			return nil, errors.New("invalid args")
   113  		}
   114  	}
   115  	c.proxy.Send(ctx, q)
   116  	resp := q.GetResponse()
   117  	return &rows{
   118  		next: &QueryResponse{
   119  			Key:         resp.Key,
   120  			Value:       resp.Value,
   121  			RangeValues: resp.RangeValues,
   122  			Stats:       resp.Stats,
   123  			Success:     resp.Success,
   124  		},
   125  	}, nil
   126  }
   127  
   128  func (c *conn) Ping() error {
   129  	result, err := c.Query(
   130  		"select value from tables where key = %s;",
   131  		[]driver.NamedValue{
   132  			{Name: "key", Ordinal: 1, Value: "default"},
   133  		},
   134  	)
   135  	if err != nil {
   136  		return err
   137  	}
   138  	if err = result.Close(); err != nil {
   139  		return err
   140  	}
   141  	return nil
   142  }
   143  
   144  var queryProxy *gproxy.QueryProxy
   145  
   146  const MEMORY = ":memory:"
   147  
   148  type Driver struct {
   149  	once sync.Once
   150  }
   151  
   152  func (d *Driver) Open(dsn string) (driver.Conn, error) {
   153  	var err error
   154  	d.once.Do(func() {
   155  		var qp *gproxy.QueryProxy
   156  		qp, err = gproxy.NewQueryProxy()
   157  		queryProxy = qp
   158  		gproxy.StartProxy(context.Background(), queryProxy)
   159  	})
   160  	return &conn{proxy: queryProxy}, err
   161  }
   162  
   163  func init() {
   164  	sql.Register("gache", &Driver{})
   165  }
   166  
   167  func GetProxy() (*gproxy.QueryProxy, error) {
   168  	return queryProxy, nil
   169  }