1
0
mirror of https://github.com/uptrace/go-clickhouse.git synced 2025-06-23 00:07:41 +02:00
Files
go-clickhouse/ch/ch.go
Vladimir Mihailenco 12a9b1e85d chore: sync API with Bun
2023-10-01 14:43:38 +03:00

171 lines
3.3 KiB
Go

package ch
import (
"database/sql"
"errors"
"fmt"
"net"
"reflect"
"github.com/uptrace/go-clickhouse/ch/chschema"
)
type (
Safe = chschema.Safe
Name = chschema.Name
Ident = chschema.Ident
CHModel = chschema.CHModel
AfterScanRowHook = chschema.AfterScanRowHook
)
func SafeQuery(query string, args ...any) chschema.QueryWithArgs {
return chschema.SafeQuery(query, args)
}
//------------------------------------------------------------------------------
type result struct {
model Model
affected int
}
var _ sql.Result = (*result)(nil)
func (res *result) Model() Model {
return res.model
}
func (res *result) RowsAffected() (int64, error) {
return int64(res.affected), nil
}
func (res *result) LastInsertId() (int64, error) {
return 0, errors.New("not implemented")
}
//------------------------------------------------------------------------------
type Error struct {
Code int32
Name string
Message string
StackTrace string
nested error // TODO: wrap/unwrap
}
func (exc *Error) Error() string {
return exc.Name + ": " + exc.Message
}
func isBadConn(err error, allowTimeout bool) bool {
if err == nil {
return false
}
if allowTimeout {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
return !netErr.Temporary()
}
}
return true
}
//------------------------------------------------------------------------------
type ListValues struct {
slice any
}
var _ chschema.QueryAppender = ListValues{}
func List(slice any) ListValues {
return ListValues{
slice: slice,
}
}
func (in ListValues) AppendQuery(fmter chschema.Formatter, b []byte) (_ []byte, err error) {
v := reflect.ValueOf(in.slice)
if v.Kind() != reflect.Slice {
return nil, fmt.Errorf("ch: In(non-slice %T)", in.slice)
}
b = appendList(fmter, b, v)
return b, nil
}
//------------------------------------------------------------------------------
type InValues struct {
slice any
}
var _ chschema.QueryAppender = InValues{}
func In(slice any) InValues {
return InValues{
slice: slice,
}
}
func (in InValues) AppendQuery(fmter chschema.Formatter, b []byte) (_ []byte, err error) {
v := reflect.ValueOf(in.slice)
if v.Kind() != reflect.Slice {
return nil, fmt.Errorf("ch: In(non-slice %T)", in.slice)
}
b = append(b, '(')
b = appendList(fmter, b, v)
b = append(b, ')')
return b, nil
}
//------------------------------------------------------------------------------
type ArrayValues struct {
slice any
}
var _ chschema.QueryAppender = ArrayValues{}
func Array(slice any) ArrayValues {
return ArrayValues{
slice: slice,
}
}
func (in ArrayValues) AppendQuery(fmter chschema.Formatter, b []byte) (_ []byte, err error) {
v := reflect.ValueOf(in.slice)
if v.Kind() != reflect.Slice {
return nil, fmt.Errorf("ch: Array(non-slice %T)", in.slice)
}
b = append(b, '[')
b = appendList(fmter, b, v)
b = append(b, ']')
return b, nil
}
//------------------------------------------------------------------------------
func appendList(fmter chschema.Formatter, b []byte, slice reflect.Value) []byte {
sliceLen := slice.Len()
if sliceLen == 0 {
return append(b, "NULL"...)
}
for i := 0; i < sliceLen; i++ {
if i > 0 {
b = append(b, ", "...)
}
elem := slice.Index(i)
if elem.Kind() == reflect.Interface {
elem = elem.Elem()
}
b = chschema.AppendValue(fmter, b, elem)
}
return b
}