-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from debeando/c3
feat - changes for c3 tool.
- Loading branch information
Showing
27 changed files
with
1,221 additions
and
15 deletions.
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
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
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,159 @@ | ||
package clickhouse | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"math" | ||
"math/big" | ||
"reflect" | ||
"time" | ||
|
||
"github.com/debeando/go-common/log" | ||
|
||
"github.com/ClickHouse/clickhouse-go/v2" | ||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver" | ||
"github.com/google/uuid" | ||
) | ||
|
||
type Column struct { | ||
Name string | ||
Kind reflect.Type | ||
Nullable bool | ||
} | ||
|
||
type Connection struct { | ||
Instance driver.Conn | ||
Name string | ||
} | ||
|
||
var instance = make(map[string]*Connection) | ||
|
||
func Instance(name string) *Connection { | ||
if instance[name] == nil { | ||
instance[name] = &Connection{} | ||
instance[name].Name = name | ||
} | ||
return instance[name] | ||
} | ||
|
||
func (c *Connection) Connect(host, port, database, username, password string) error { | ||
var err error | ||
|
||
if c.Instance != nil { | ||
return errors.New("ClickHouse can't connect because instance is empty.") | ||
} | ||
|
||
log.DebugWithFields("ClickHouse connection settings.", log.Fields{ | ||
"Host": host, | ||
"Port": port, | ||
"Database": database, | ||
"Username": username, | ||
"Password": password, | ||
}) | ||
|
||
c.Instance, err = clickhouse.Open(&clickhouse.Options{ | ||
Addr: []string{fmt.Sprintf("%s:%s", host, port)}, | ||
Auth: clickhouse.Auth{ | ||
Database: database, | ||
Username: username, | ||
Password: password, | ||
}, | ||
}) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err = c.Instance.Ping(context.Background()); err != nil { | ||
return err | ||
} | ||
|
||
log.Debug("ClickHouse connected!") | ||
|
||
return nil | ||
} | ||
|
||
func (c *Connection) Query(query string) (map[int]map[string]any, error) { | ||
log.DebugWithFields("ClickHouse execute.", log.Fields{ | ||
"Query": query, | ||
}) | ||
|
||
rows, err := c.Instance.Query(context.Background(), query) | ||
if err != nil { | ||
return nil, err | ||
} | ||
defer rows.Close() | ||
|
||
row_id := 0 | ||
columns := []Column{} | ||
types := rows.ColumnTypes() | ||
dataset := make(map[int]map[string]any) | ||
|
||
for _, c := range types { | ||
columns = append(columns, Column{ | ||
Name: c.Name(), | ||
Kind: c.ScanType(), | ||
Nullable: c.Nullable(), | ||
}) | ||
} | ||
|
||
values := make([]any, len(types)) | ||
|
||
for i := range types { | ||
values[i] = reflect.New(types[i].ScanType()).Interface() | ||
} | ||
|
||
for rows.Next() { | ||
err = rows.Scan(values...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
row := make(map[string]any) | ||
|
||
for i, v := range values { | ||
switch v := v.(type) { | ||
case *bool: | ||
row[columns[i].Name] = *v | ||
case *string: | ||
row[columns[i].Name] = *v | ||
case *int8: | ||
row[columns[i].Name] = *v | ||
case *int16: | ||
row[columns[i].Name] = *v | ||
case *int32: | ||
row[columns[i].Name] = *v | ||
case *int64: | ||
row[columns[i].Name] = *v | ||
case *uint8: | ||
row[columns[i].Name] = *v | ||
case **uint8: | ||
row[columns[i].Name] = *v | ||
case *uint16: | ||
row[columns[i].Name] = *v | ||
case *uint32: | ||
row[columns[i].Name] = *v | ||
case *uint64: | ||
row[columns[i].Name] = *v | ||
case **big.Int: | ||
row[columns[i].Name] = *v | ||
case *float32, *float64: | ||
if value := *(v.(*float64)); !math.IsNaN(value) { | ||
row[columns[i].Name] = value | ||
} | ||
case *time.Time: | ||
row[columns[i].Name] = v.Format("2006-01-02 15:04:05") | ||
case *uuid.UUID: | ||
row[columns[i].Name] = *v | ||
default: | ||
row[columns[i].Name] = nil | ||
} | ||
} | ||
|
||
dataset[row_id] = row | ||
|
||
row_id++ | ||
} | ||
|
||
return dataset, 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,27 @@ | ||
package exec | ||
|
||
import ( | ||
"fmt" | ||
"os/exec" | ||
"syscall" | ||
|
||
"github.com/debeando/go-common/cast" | ||
) | ||
|
||
func PGrep(cmd string) int64 { | ||
stdout, _ := Command(fmt.Sprintf("/usr/bin/pgrep -f '%s'", cmd)) | ||
|
||
return cast.StringToInt64(stdout) | ||
} | ||
|
||
func Command(cmd string) (stdout string, exitcode int) { | ||
out, err := exec.Command("/bin/bash", "-c", cmd).Output() | ||
|
||
if exitError, ok := err.(*exec.ExitError); ok { | ||
ws := exitError.Sys().(syscall.WaitStatus) | ||
exitcode = ws.ExitStatus() | ||
} | ||
|
||
stdout = string(out[:]) | ||
return | ||
} |
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,50 @@ | ||
package file | ||
|
||
import ( | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/debeando/go-common/cast" | ||
) | ||
|
||
func Exist(path string) bool { | ||
info, err := os.Stat(path) | ||
if os.IsNotExist(err) { | ||
return false | ||
} | ||
return !info.IsDir() | ||
} | ||
|
||
func Read(path string) []byte { | ||
c, _ := ioutil.ReadFile(path) | ||
return c | ||
} | ||
|
||
func ReadAsString(path string) string { | ||
return string(Read(path)) | ||
} | ||
|
||
func ReadExpandEnv(path string) []byte { | ||
return []byte(os.ExpandEnv(ReadAsString(path))) | ||
} | ||
|
||
func ReadExpandEnvAsString(path string) string { | ||
return string(ReadExpandEnv(path)) | ||
} | ||
|
||
func Name(n string) string { | ||
return n[:len(n)-len(filepath.Ext(n))] | ||
} | ||
|
||
func Dir(path string) string { | ||
return filepath.Dir(path) | ||
} | ||
|
||
func GetInt64(path string) int64 { | ||
lines := ReadAsString(path) | ||
if len(lines) > 0 { | ||
return cast.StringToInt64(lines) | ||
} | ||
return 0 | ||
} |
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,31 @@ | ||
package file_test | ||
|
||
import ( | ||
"os" | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/debeando/go-common/file" | ||
) | ||
|
||
var wd string | ||
|
||
func TestMain(m *testing.M) { | ||
wd, _ = os.Getwd() | ||
} | ||
|
||
func TestGetInt64FromFile(t *testing.T) { | ||
expected := int64(1234567890) | ||
result := common.GetInt64FromFile(wd + "/../assets/tests/int64.txt") | ||
|
||
if result != expected { | ||
t.Error("Expected: int64(1234567890)") | ||
} | ||
|
||
expected = int64(0) | ||
result = common.GetInt64FromFile(wd + "/../assets/tests/int64.log") | ||
|
||
if result != expected { | ||
t.Error("Expected: int64(0)") | ||
} | ||
} |
Oops, something went wrong.