ok
This commit is contained in:
@@ -60,9 +60,9 @@ func (r *AnalyticsRepo) Funnel(ctx context.Context, q FunnelQuery) (*model.Query
|
||||
|
||||
args := []any{
|
||||
clickhouse.Named("workspace_id", q.WorkspaceID),
|
||||
clickhouse.DateNamed("from", q.From, clickhouse.MilliSeconds),
|
||||
clickhouse.DateNamed("to", q.To, clickhouse.MilliSeconds),
|
||||
clickhouse.Named("window_seconds", q.WindowSeconds),
|
||||
clickhouse.Named("from", chTime(q.From)),
|
||||
clickhouse.Named("to", chTime(q.To)),
|
||||
clickhouse.Named("window_seconds", chUint(uint64(q.WindowSeconds))),
|
||||
}
|
||||
for i, name := range q.Steps {
|
||||
args = append(args, clickhouse.Named(fmt.Sprintf("step%d", i), name))
|
||||
@@ -112,8 +112,8 @@ func (r *AnalyticsRepo) Retention(ctx context.Context, q RetentionQuery) (*model
|
||||
|
||||
rows, err := r.ch.Query(ctx, sql,
|
||||
clickhouse.Named("workspace_id", q.WorkspaceID),
|
||||
clickhouse.DateNamed("from", q.From, clickhouse.MilliSeconds),
|
||||
clickhouse.DateNamed("to", q.To, clickhouse.MilliSeconds),
|
||||
clickhouse.Named("from", chTime(q.From)),
|
||||
clickhouse.Named("to", chTime(q.To)),
|
||||
clickhouse.Named("initial_event", q.InitialEvent),
|
||||
clickhouse.Named("return_event", q.ReturnEvent),
|
||||
)
|
||||
@@ -148,11 +148,11 @@ func (r *AnalyticsRepo) Sessions(ctx context.Context, q SessionQuery) (*model.Qu
|
||||
|
||||
args := []any{
|
||||
clickhouse.Named("workspace_id", q.WorkspaceID),
|
||||
clickhouse.DateNamed("from", q.From, clickhouse.MilliSeconds),
|
||||
clickhouse.DateNamed("to", q.To, clickhouse.MilliSeconds),
|
||||
clickhouse.Named("timeout_seconds", q.TimeoutSeconds),
|
||||
clickhouse.Named("limit", uint32(q.Limit)),
|
||||
clickhouse.Named("offset", uint32(q.Offset)),
|
||||
clickhouse.Named("from", chTime(q.From)),
|
||||
clickhouse.Named("to", chTime(q.To)),
|
||||
clickhouse.Named("timeout_seconds", chUint(uint64(q.TimeoutSeconds))),
|
||||
clickhouse.Named("limit", chUint(uint64(q.Limit))),
|
||||
clickhouse.Named("offset", chUint(uint64(q.Offset))),
|
||||
}
|
||||
if q.UserID != "" {
|
||||
args = append(args, clickhouse.Named("user_id", q.UserID))
|
||||
|
||||
@@ -3,6 +3,8 @@ package repo
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/ClickHouse/clickhouse-go/v2"
|
||||
"github.com/ClickHouse/clickhouse-go/v2/lib/driver"
|
||||
@@ -11,6 +13,18 @@ import (
|
||||
"github.com/dbiz/cdp/data-layer/api/internal/templates"
|
||||
)
|
||||
|
||||
// chTime formats a Go time.Time for ClickHouse server-side query parameters.
|
||||
// clickhouse-go v2 routes args declared via {name:Type} syntax through the
|
||||
// server-side parameter protocol, which only accepts string values -- typed
|
||||
// helpers like clickhouse.DateNamed fail with
|
||||
// "expected string value in NamedValue for query parameter".
|
||||
// We emit the format ClickHouse parses for DateTime64(3,'UTC').
|
||||
func chTime(t time.Time) string {
|
||||
return t.UTC().Format("2006-01-02 15:04:05.000")
|
||||
}
|
||||
|
||||
func chUint(n uint64) string { return strconv.FormatUint(n, 10) }
|
||||
|
||||
type EventRepo struct {
|
||||
ch driver.Conn
|
||||
tpl *templates.Store
|
||||
@@ -39,10 +53,10 @@ func (r *EventRepo) QueryEvents(ctx context.Context, q model.EventQuery) (*model
|
||||
|
||||
args := []any{
|
||||
clickhouse.Named("workspace_id", q.WorkspaceID),
|
||||
clickhouse.DateNamed("from", q.From, clickhouse.MilliSeconds),
|
||||
clickhouse.DateNamed("to", q.To, clickhouse.MilliSeconds),
|
||||
clickhouse.Named("limit", uint32(q.Limit)),
|
||||
clickhouse.Named("offset", uint32(q.Offset)),
|
||||
clickhouse.Named("from", chTime(q.From)),
|
||||
clickhouse.Named("to", chTime(q.To)),
|
||||
clickhouse.Named("limit", chUint(uint64(q.Limit))),
|
||||
clickhouse.Named("offset", chUint(uint64(q.Offset))),
|
||||
}
|
||||
if q.UserID != "" {
|
||||
args = append(args, clickhouse.Named("user_id", q.UserID))
|
||||
@@ -73,8 +87,8 @@ func (r *EventRepo) QueryProfileTimeline(ctx context.Context, workspaceID, userI
|
||||
rows, err := r.ch.Query(ctx, sql,
|
||||
clickhouse.Named("workspace_id", workspaceID),
|
||||
clickhouse.Named("user_id", userID),
|
||||
clickhouse.Named("limit", uint32(limit)),
|
||||
clickhouse.Named("offset", uint32(offset)),
|
||||
clickhouse.Named("limit", chUint(uint64(limit))),
|
||||
clickhouse.Named("offset", chUint(uint64(offset))),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("clickhouse query: %w", err)
|
||||
@@ -146,7 +160,8 @@ func newScanTarget(typeName string) any {
|
||||
var v bool
|
||||
return &v
|
||||
case "time.Time":
|
||||
return new(any) // let driver fill, deref below handles it
|
||||
var v time.Time
|
||||
return &v
|
||||
case "map[string]string":
|
||||
var v map[string]string
|
||||
return &v
|
||||
@@ -186,6 +201,8 @@ func derefScanTarget(p any) any {
|
||||
return *v
|
||||
case *[]string:
|
||||
return *v
|
||||
case *time.Time:
|
||||
return *v
|
||||
case *any:
|
||||
return *v
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user