-
Notifications
You must be signed in to change notification settings - Fork 568
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e734513
commit fde0472
Showing
10 changed files
with
1,107 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 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 | ||
VariantWithType = chcol.VariantWithType | ||
) | ||
|
||
// 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) VariantWithType { | ||
return chcol.NewVariantWithType(v, chType) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// 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, | ||
}, nil, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
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.VariantWithType | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// 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 chcol | ||
|
||
import ( | ||
"database/sql/driver" | ||
"encoding/json" | ||
) | ||
|
||
// Variant represents a ClickHouse Variant type that can hold multiple possible types | ||
type Variant struct { | ||
value any | ||
} | ||
|
||
// NewVariant creates a new Variant with the given value | ||
func NewVariant(v any) Variant { | ||
return Variant{value: v} | ||
} | ||
|
||
// Nil returns true if the underlying value is nil. | ||
func (v Variant) Nil() bool { | ||
return v.value == nil | ||
} | ||
|
||
// Any returns the underlying value as any. Same as Interface. | ||
func (v Variant) Any() any { | ||
return v.value | ||
} | ||
|
||
// Interface returns the underlying value as interface{}. Same as Any. | ||
func (v Variant) Interface() interface{} { | ||
return v.value | ||
} | ||
|
||
// Int returns the value as an int if possible | ||
func (v Variant) Int() (int, bool) { | ||
if i, ok := v.value.(int); ok { | ||
return i, true | ||
} | ||
|
||
return 0, false | ||
} | ||
|
||
// Int64 returns the value as an int64 if possible | ||
func (v Variant) Int64() (int64, bool) { | ||
if i, ok := v.value.(int64); ok { | ||
return i, true | ||
} | ||
|
||
return 0, false | ||
} | ||
|
||
// String returns the value as a string if possible | ||
func (v Variant) String() (string, bool) { | ||
if s, ok := v.value.(string); ok { | ||
return s, true | ||
} | ||
|
||
return "", false | ||
} | ||
|
||
// Bool returns the value as an bool if possible | ||
func (v Variant) Bool() (bool, bool) { | ||
if b, ok := v.value.(bool); ok { | ||
return b, true | ||
} | ||
|
||
return false, false | ||
} | ||
|
||
// MarshalJSON implements the json.Marshaler interface | ||
func (v *Variant) MarshalJSON() ([]byte, error) { | ||
return json.Marshal(v.value) | ||
} | ||
|
||
// Scan implements the sql.Scanner interface | ||
func (v *Variant) Scan(value interface{}) error { | ||
v.value = value | ||
return nil | ||
} | ||
|
||
// Value implements the driver.Valuer interface | ||
func (v Variant) Value() (driver.Value, error) { | ||
return v.value, nil | ||
} | ||
|
||
func (v Variant) WithType(chType string) VariantWithType { | ||
return VariantWithType{ | ||
Variant: v, | ||
chType: chType, | ||
} | ||
} | ||
|
||
// VariantWithType is Variant with an extra value for specifying the preferred ClickHouse type for column encoding | ||
type VariantWithType struct { | ||
Variant | ||
chType string | ||
} | ||
|
||
// NewVariantWithType creates a new Variant with the given value and ClickHouse type | ||
func NewVariantWithType(v any, chType string) VariantWithType { | ||
return VariantWithType{ | ||
Variant: Variant{value: v}, | ||
chType: chType, | ||
} | ||
} | ||
|
||
// Type returns the ClickHouse type as a string. | ||
func (v VariantWithType) Type() string { | ||
return v.chType | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// 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 chcol | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestVariant_Nil(t *testing.T) { | ||
v := NewVariant(nil) | ||
|
||
if !v.Nil() { | ||
t.Fatalf("expected variant to be nil") | ||
} | ||
} | ||
|
||
func TestVariant_Int64(t *testing.T) { | ||
var in int64 = 42 | ||
|
||
v := NewVariant(in) | ||
|
||
out, ok := v.Int64() | ||
if !ok { | ||
t.Fatalf("failed to get int64 from variant") | ||
} else if out != in { | ||
t.Fatalf("incorrect value from variant. expected: %d got: %d", in, out) | ||
} | ||
} | ||
|
||
func TestVariant_String(t *testing.T) { | ||
in := "test" | ||
|
||
v := NewVariant(in) | ||
|
||
out, ok := v.String() | ||
if !ok { | ||
t.Fatalf("failed to get string from variant") | ||
} else if out != in { | ||
t.Fatalf("incorrect value from variant. expected: %s got: %s", in, out) | ||
} | ||
} | ||
|
||
func TestVariant_TypeSwitch(t *testing.T) { | ||
var in any | ||
|
||
v := NewVariant(in) | ||
|
||
switch v.Any().(type) { | ||
case int64: | ||
t.Fatalf("unexpected int64 value from variant") | ||
case string: | ||
t.Fatalf("unexpected string value from variant") | ||
case nil: | ||
default: | ||
t.Fatalf("expected nil value from variant") | ||
} | ||
} |
Oops, something went wrong.