Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
jkaflik committed Apr 13, 2023
2 parents 9d4f951 + d14aec8 commit 558434c
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 11 deletions.
22 changes: 22 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
changelog:
exclude:
labels:
- ignore-for-release
authors:
- dependabot
categories:
- title: Breaking Changes 🚨
labels:
- Semver-Major
- breaking-change
- title: Enhancements 🎉
labels:
- Semver-Minor
- enhancement
- title: Fixes 🐛
labels:
- Semver-Patch
- fix
- title: Other Changes 🛠
labels:
- "*"
35 changes: 25 additions & 10 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,32 +66,47 @@ func bind(tz *time.Location, query string, args ...interface{}) (string, error)
return query, nil
}
var (
haveNamed bool
haveNumeric bool
havePositional bool
)

allArgumentsNamed, err := checkAllNamedArguments(args...)
if err != nil {
return "", err
}

if allArgumentsNamed {
return bindNamed(tz, query, args...)
}

haveNumeric = bindNumericRe.MatchString(query)
havePositional = bindPositionalRe.MatchString(query)
if haveNumeric && havePositional {
return "", ErrBindMixedParamsFormats
}
if haveNumeric {
return bindNumeric(tz, query, args...)
}
return bindPositional(tz, query, args...)
}

func checkAllNamedArguments(args ...interface{}) (bool, error) {
var (
haveNamed bool
haveAnonymous bool
)
for _, v := range args {
switch v.(type) {
case driver.NamedValue, driver.NamedDateValue:
haveNamed = true
default:
haveAnonymous = true
}
if haveNamed && (haveNumeric || havePositional) {
return "", ErrBindMixedParamsFormats
if haveNamed && haveAnonymous {
return haveNamed, ErrBindMixedParamsFormats
}
}
if haveNamed {
return bindNamed(tz, query, args...)
}
if haveNumeric {
return bindNumeric(tz, query, args...)
}
return bindPositional(tz, query, args...)
return haveNamed, nil
}

var bindPositionCharRe = regexp.MustCompile(`[?]`)
Expand Down
17 changes: 16 additions & 1 deletion bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,13 +225,14 @@ func TestBindPositional(t *testing.T) {
ANS col4 = ?
AND null_coll = ?
)
`, 1, 2, "I'm a string param", nil)
`, 1, 2, "I'm a string param", nil, Named("namedArg", nil))
assert.Error(t, err)

var nilPtr *bool = nil
var nilPtrPtr **interface{} = nil
valuedPtr := &([]interface{}{123}[0])
nilValuePtr := &([]interface{}{nil}[0])

_, err = bind(time.Local, `
SELECT * FROM t WHERE col = ?
AND col2 = ?
Expand Down Expand Up @@ -330,6 +331,20 @@ func TestFormatMap(t *testing.T) {
assert.Equal(t, "map('a', 1)", val)
}

func TestBindNamedWithTernaryOperator(t *testing.T) {
sqls := []string{
`SELECT if(@arg1,@arg2,@arg3)`, // correct
`SELECT @arg1?@arg2:@arg3`, // failed here
}
for _, sql := range sqls {
_, err := bind(time.Local, sql,
Named("arg1", 0),
Named("arg2", 1),
Named("arg3", 2))
assert.NoError(t, err)
}
}

func BenchmarkBindNumeric(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
Expand Down
26 changes: 26 additions & 0 deletions lib/column/nullable.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,32 @@ func (col *Nullable) ScanRow(dest interface{}, row int) error {
if col.enable {
switch col.nulls.Row(row) {
case 1:
switch v := dest.(type) {
case **uint64:
*v = nil
case **int64:
*v = nil
case **uint32:
*v = nil
case **int32:
*v = nil
case **uint16:
*v = nil
case **int16:
*v = nil
case **uint8:
*v = nil
case **int8:
*v = nil
case **string:
*v = nil
case **float32:
*v = nil
case **float64:
*v = nil
case **time.Time:
*v = nil
}
if scan, ok := dest.(sql.Scanner); ok {
return scan.Scan(nil)
}
Expand Down
58 changes: 58 additions & 0 deletions tests/issues/955_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package issues

import (
"context"
"github.com/ClickHouse/clickhouse-go/v2"
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
clickhouse_tests "github.com/ClickHouse/clickhouse-go/v2/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"reflect"
"testing"
)

func Test955(t *testing.T) {
var (
conn, err = clickhouse_tests.GetConnection("issues", clickhouse.Settings{
"max_execution_time": 60,
}, nil, &clickhouse.Compression{
Method: clickhouse.CompressionLZ4,
})
)
ctx := context.Background()
require.NoError(t, err)
const ddl = `
CREATE TABLE test_955 (
Col1 Nullable(UInt64)
) Engine MergeTree() ORDER BY tuple()
`
defer func() {
conn.Exec(ctx, "DROP TABLE IF EXISTS test_955")
}()
require.NoError(t, conn.Exec(ctx, ddl))
const baseValues = `
INSERT INTO test_955 VALUES (123), (NULL)
`
require.NoError(t, conn.Exec(ctx, baseValues))

rows, err := conn.Query(ctx, "SELECT * FROM test_955")
require.NoError(t, err)
defer func(rows driver.Rows) {
_ = rows.Close()
}(rows)

records := make([][]any, 0)
for rows.Next() {
record := make([]any, 0, len(rows.ColumnTypes()))
for _, ct := range rows.ColumnTypes() {
record = append(record, reflect.New(ct.ScanType()).Interface())
}
err = rows.Scan(record...)
require.NoError(t, err)

records = append(records, record)
}
var value *uint64
value = nil
assert.Equal(t, value, *records[1][0].(**uint64))
}

0 comments on commit 558434c

Please sign in to comment.