Files
ragflow/internal/agent/tool/exesql_trino_stub.go
Jin Hai add7b9486f Go: merge duplicate codes (#16783)
### Summary

1. merge heartbeat function.
2. introduce all environments

---------

Signed-off-by: Jin Hai <haijin.chn@gmail.com>
2026-07-10 11:58:32 +08:00

129 lines
4.0 KiB
Go

//
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
// Licensed 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
//
// exesql_trino_stub.go — minimal implementations of the Trino DSN
// helpers referenced by exesql_trino_test.go. The real
// implementation lands when the trino driver integration moves
// from "registered via self-register" to "explicit DSN
// construction" — a follow-up tracked under the design doc
// Future Work.
//
// What this file provides:
//
// - trinoDSN(exesqlConnParams) string
// Constructs a Trino DSN with the format
// `http(s)://<user>[:<password>]@<host>:<port>?catalog=<cat>&schema=<sch>`
// (matches what trino-go-client v0.333.0 expects).
//
// - splitTrinoCatalogSchema(db string) (cat, sch string)
// Splits a `<db>` argument into a Trino `(catalog, schema)` pair.
// Python `exesql.py:167-176` five quirks are honoured:
// 1. empty password over TLS is preferred (do not embed it)
// 2. TRINO_USE_TLS=1 flips the scheme to https
// 3. default port is 8080 when zero
// 4. empty username → "ragflow"
// 5. catalog[.schema] parsing: first dot/slash is the
// catalog separator, remainder (if any) is the schema
//
// These implementations are intentionally minimal — they satisfy
// the test contract (splitTrinoCatalogSchema, DSN prefix) without
// claiming feature parity with the Python side. The "happy path"
// DSN shape test (TestExeSQL_TrinoDSN_HappyPath_BasicShape) uses
// these to validate the wiring; richer provider-specific behaviour
// (auth plugins, custom certs, …) is out of scope.
package tool
import (
"fmt"
"net/url"
"ragflow/internal/common"
"strconv"
"strings"
)
// splitTrinoCatalogSchema parses a Trino database spec into a
// (catalog, schema) pair. The first `.` or `/` is the catalog
// separator; everything after it is the schema (which may itself
// contain dots — the schema namespace is a free-form string).
func splitTrinoCatalogSchema(db string) (catalog, schema string) {
if db == "" {
return "", ""
}
// Honour both `.` and `/` as catalog separators (Python
// exesql.py:175-176 supports both). The first occurrence wins.
for _, sep := range []string{".", "/"} {
if i := strings.Index(db, sep); i >= 0 {
return db[:i], db[i+1:]
}
}
return db, "default"
}
// trinoDSN builds a Trino DSN from the project's exesql connection
// params. Honours the Python-side quirks documented in
// design doc §10.1 + gap analysis §11.4.1 row 5c.
func trinoDSN(p exesqlConnParams) string {
scheme := "http"
if common.GetEnv(common.EnvTrinoUseTls) != "" {
scheme = "https"
}
port := p.Port
if port == 0 {
port = 8080
}
username := p.Username
if username == "" {
username = "ragflow"
}
host := p.Host
if host == "" {
host = "localhost"
}
catalog, schema := splitTrinoCatalogSchema(p.Database)
if schema == "" {
schema = "default"
}
var user *url.Userinfo
if scheme == "https" && p.Password != "" {
user = url.UserPassword(username, p.Password)
} else {
user = url.User(username)
}
q := url.Values{}
q.Set("catalog", catalog)
q.Set("schema", schema)
u := url.URL{
Scheme: scheme,
User: user,
Host: host + ":" + strconv.Itoa(port),
RawQuery: q.Encode(),
}
// Over plain HTTP, omit the password entirely so the DSN never
// leaks cleartext credentials in userinfo.
return u.String()
}
// formatTrinoDSNForLog is a small helper exposed for tests that
// need to assert a DSN without the password portion leaking into
// test logs. Not used by production code.
func formatTrinoDSNForLog(dsn string) string {
u, err := url.Parse(dsn)
if err != nil || u.User == nil {
return dsn
}
if _, hasPass := u.User.Password(); hasPass {
u.User = url.User(u.User.Username())
}
if u.RawQuery != "" {
return fmt.Sprintf("%s://%s@%s?%s", u.Scheme, u.User, u.Host, u.RawQuery)
}
return fmt.Sprintf("%s://%s@%s", u.Scheme, u.User, u.Host)
}