Skip to content

Commit

Permalink
Merge branch 'main' into insert-performance-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
serprex authored Jan 16, 2025
2 parents 73d9f63 + 75a2e2a commit c2e21ab
Show file tree
Hide file tree
Showing 31 changed files with 3,128 additions and 26 deletions.
47 changes: 47 additions & 0 deletions chcol.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Licensed to ClickHouse, Inc. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. ClickHouse, Inc. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package clickhouse

import "github.com/ClickHouse/clickhouse-go/v2/lib/chcol"

// Re-export chcol types/funcs to top level clickhouse package

type (
Variant = chcol.Variant
Dynamic = chcol.Dynamic
)

// NewVariant creates a new Variant with the given value
func NewVariant(v any) Variant {
return chcol.NewVariant(v)
}

// NewVariantWithType creates a new Variant with the given value and ClickHouse type
func NewVariantWithType(v any, chType string) Variant {
return chcol.NewVariantWithType(v, chType)
}

// NewDynamic creates a new Dynamic with the given value
func NewDynamic(v any) Dynamic {
return chcol.NewDynamic(v)
}

// NewDynamicWithType creates a new Dynamic with the given value and ClickHouse type
func NewDynamicWithType(v any, chType string) Dynamic {
return chcol.NewDynamicWithType(v, chType)
}
6 changes: 6 additions & 0 deletions clickhouse_std.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,10 +445,16 @@ func (r *stdRows) ColumnTypePrecisionScale(idx int) (precision, scale int64, ok
switch col := r.rows.block.Columns[idx].(type) {
case *column.Decimal:
return col.Precision(), col.Scale(), true
case *column.DateTime64:
p, ok := col.Precision()
return p, 0, ok
case interface{ Base() column.Interface }:
switch col := col.Base().(type) {
case *column.Decimal:
return col.Precision(), col.Scale(), true
case *column.DateTime64:
p, ok := col.Precision()
return p, 0, ok
}
}
return 0, 0, false
Expand Down
141 changes: 141 additions & 0 deletions examples/clickhouse_api/dynamic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Licensed to ClickHouse, Inc. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. ClickHouse, Inc. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package clickhouse_api

import (
"context"
"fmt"
"github.com/ClickHouse/clickhouse-go/v2"
)

func DynamicExample() error {
ctx := context.Background()

conn, err := GetNativeConnection(clickhouse.Settings{
"allow_experimental_dynamic_type": true,
}, nil, nil)
if err != nil {
return err
}

if !CheckMinServerVersion(conn, 24, 8, 0) {
fmt.Print("unsupported clickhouse version for Dynamic type")
return nil
}

err = conn.Exec(ctx, "DROP TABLE IF EXISTS go_dynamic_example")
if err != nil {
return err
}

err = conn.Exec(ctx, `
CREATE TABLE go_dynamic_example (
c Dynamic
) ENGINE = Memory
`)
if err != nil {
return err
}

batch, err := conn.PrepareBatch(ctx, "INSERT INTO go_dynamic_example (c)")
if err != nil {
return err
}

if err = batch.Append(true); err != nil {
return err
}

if err = batch.Append(int64(42)); err != nil {
return err
}

if err = batch.Append("example"); err != nil {
return err
}

if err = batch.Append(clickhouse.NewDynamic("example dynamic")); err != nil {
return err
}

if err = batch.Append(clickhouse.NewDynamicWithType("example dynamic with specific type", "String")); err != nil {
return err
}

if err = batch.Append(nil); err != nil {
return err
}

if err = batch.Send(); err != nil {
return err
}

// Switch on Go Type

rows, err := conn.Query(ctx, "SELECT c FROM go_dynamic_example")
if err != nil {
return err
}

for i := 0; rows.Next(); i++ {
var row clickhouse.Dynamic
err := rows.Scan(&row)
if err != nil {
return fmt.Errorf("failed to scan row index %d: %w", i, err)
}

switch row.Any().(type) {
case bool:
fmt.Printf("row at index %d is Bool: %v\n", i, row.Any())
case int64:
fmt.Printf("row at index %d is Int64: %v\n", i, row.Any())
case string:
fmt.Printf("row at index %d is String: %v\n", i, row.Any())
case nil:
fmt.Printf("row at index %d is NULL\n", i)
}
}

// Switch on ClickHouse Type

rows, err = conn.Query(ctx, "SELECT c FROM go_dynamic_example")
if err != nil {
return err
}

for i := 0; rows.Next(); i++ {
var row clickhouse.Dynamic
err := rows.Scan(&row)
if err != nil {
return fmt.Errorf("failed to scan row index %d: %w", i, err)
}

switch row.Type() {
case "Bool":
fmt.Printf("row at index %d is bool: %v\n", i, row.Any())
case "Int64":
fmt.Printf("row at index %d is int64: %v\n", i, row.Any())
case "String":
fmt.Printf("row at index %d is string: %v\n", i, row.Any())
case "":
fmt.Printf("row at index %d is nil\n", i)
}
}

return nil
}
8 changes: 8 additions & 0 deletions examples/clickhouse_api/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,11 @@ func TestSSL(t *testing.T) {
func TestSSLNoVerify(t *testing.T) {
require.NoError(t, SSLNoVerifyVersion())
}

func TestVariantExample(t *testing.T) {
require.NoError(t, VariantExample())
}

func TestDynamicExample(t *testing.T) {
require.NoError(t, DynamicExample())
}
4 changes: 4 additions & 0 deletions examples/clickhouse_api/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ func GetNativeTestEnvironment() (clickhouse_tests.ClickHouseTestEnvironment, err
func GetNativeConnectionWithOptions(settings clickhouse.Settings, tlsConfig *tls.Config, compression *clickhouse.Compression) (driver.Conn, error) {
return clickhouse_tests.GetConnection(TestSet, settings, tlsConfig, compression)
}

func CheckMinServerVersion(conn driver.Conn, major, minor, patch uint64) bool {
return clickhouse_tests.CheckMinServerServerVersion(conn, major, minor, patch)
}
143 changes: 143 additions & 0 deletions examples/clickhouse_api/variant.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Licensed to ClickHouse, Inc. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. ClickHouse, Inc. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package clickhouse_api

import (
"context"
"fmt"

"github.com/ClickHouse/clickhouse-go/v2"
)

func VariantExample() error {
ctx := context.Background()

conn, err := GetNativeConnection(clickhouse.Settings{
"allow_experimental_variant_type": true,
"allow_suspicious_variant_types": true,
}, nil, nil)
if err != nil {
return err
}

if !CheckMinServerVersion(conn, 24, 4, 0) {
fmt.Print("unsupported clickhouse version for Variant type")
return nil
}

err = conn.Exec(ctx, "DROP TABLE IF EXISTS go_variant_example")
if err != nil {
return err
}

err = conn.Exec(ctx, `
CREATE TABLE go_variant_example (
c Variant(Bool, Int64, String)
) ENGINE = Memory
`)
if err != nil {
return err
}

batch, err := conn.PrepareBatch(ctx, "INSERT INTO go_variant_example (c)")
if err != nil {
return err
}

if err = batch.Append(true); err != nil {
return err
}

if err = batch.Append(int64(42)); err != nil {
return err
}

if err = batch.Append("example"); err != nil {
return err
}

if err = batch.Append(clickhouse.NewVariant("example variant")); err != nil {
return err
}

if err = batch.Append(clickhouse.NewVariantWithType("example variant with specific type", "String")); err != nil {
return err
}

if err = batch.Append(nil); err != nil {
return err
}

if err = batch.Send(); err != nil {
return err
}

// Switch on Go Type

rows, err := conn.Query(ctx, "SELECT c FROM go_variant_example")
if err != nil {
return err
}

for i := 0; rows.Next(); i++ {
var row clickhouse.Variant
err := rows.Scan(&row)
if err != nil {
return fmt.Errorf("failed to scan row index %d: %w", i, err)
}

switch row.Any().(type) {
case bool:
fmt.Printf("row at index %d is Bool: %v\n", i, row.Any())
case int64:
fmt.Printf("row at index %d is Int64: %v\n", i, row.Any())
case string:
fmt.Printf("row at index %d is String: %v\n", i, row.Any())
case nil:
fmt.Printf("row at index %d is NULL\n", i)
}
}

// Switch on ClickHouse Type

rows, err = conn.Query(ctx, "SELECT c FROM go_variant_example")
if err != nil {
return err
}

for i := 0; rows.Next(); i++ {
var row clickhouse.Variant
err := rows.Scan(&row)
if err != nil {
return fmt.Errorf("failed to scan row index %d: %w", i, err)
}

switch row.Type() {
case "Bool":
fmt.Printf("row at index %d is bool: %v\n", i, row.Any())
case "Int64":
fmt.Printf("row at index %d is int64: %v\n", i, row.Any())
case "String":
fmt.Printf("row at index %d is string: %v\n", i, row.Any())
case "":
fmt.Printf("row at index %d is nil\n", i)
}
}

return nil
}
Loading

0 comments on commit c2e21ab

Please sign in to comment.