1
0
mirror of https://github.com/uptrace/go-clickhouse.git synced 2025-06-08 23:26:11 +02:00

121 lines
2.3 KiB
Go
Raw Normal View History

2022-01-23 09:36:24 +02:00
package ch
import (
"database/sql"
"errors"
"fmt"
"net"
"reflect"
"github.com/uptrace/go-clickhouse/ch/chschema"
)
type (
Safe = chschema.Safe
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 InValues struct {
slice reflect.Value
err error
}
var _ chschema.QueryAppender = InValues{}
func In(slice any) InValues {
v := reflect.ValueOf(slice)
if v.Kind() != reflect.Slice {
return InValues{
err: fmt.Errorf("ch: In(non-slice %T)", slice),
}
}
return InValues{
slice: v,
}
}
func (in InValues) AppendQuery(fmter chschema.Formatter, b []byte) (_ []byte, err error) {
if in.err != nil {
return nil, in.err
}
return appendIn(fmter, b, in.slice), nil
}
func appendIn(fmter chschema.Formatter, b []byte, slice reflect.Value) []byte {
sliceLen := slice.Len()
for i := 0; i < sliceLen; i++ {
if i > 0 {
b = append(b, ", "...)
}
elem := slice.Index(i)
if elem.Kind() == reflect.Interface {
elem = elem.Elem()
}
if elem.Kind() == reflect.Slice {
b = append(b, '(')
b = appendIn(fmter, b, elem)
b = append(b, ')')
} else {
b = chschema.AppendValue(fmter, b, elem)
}
}
return b
}