mirror of
https://github.com/hanzoai/sqlbuilder.git
synced 2026-10-01 00:37:42 +00:00
Fork huandu/go-sqlbuilder v1.39.1 to hanzoai/sqlbuilder; debrand ClickHouse flavor -> Datastore
- go.mod module path -> github.com/hanzoai/sqlbuilder (package name kept: sqlbuilder) - Rename exported Flavor constant ClickHouse -> Datastore (same iota ordinal 6, behavior byte-identical): const decl, all case labels (Interpolate/Quote/ PrepareInsertIgnore/args/select/union), Flavor.String() literal "ClickHouse" -> "Datastore", and the name<->flavor test map. - Rename unexported dialect helper clickhouseInterpolate -> datastoreInterpolate. - Rename example ExampleInsertBuilder_insertIgnore_clickhouse -> _datastore. - Update tests + README flavor list to Datastore. - Keep upstream MIT LICENSE; add NOTICE recording the fork + rename. Dialect SQL output unchanged; only the identifier is renamed.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
Fork of github.com/huandu/go-sqlbuilder (MIT), renamed to github.com/hanzoai/sqlbuilder; the ClickHouse SQL-dialect flavor constant is renamed to Datastore for the Hanzo datastore debrand. Behavior unchanged.
|
||||
@@ -249,7 +249,7 @@ The older `OrderBy` method combined with `Asc`/`Desc` is still available but dep
|
||||
|
||||
SQL syntax and parameter placeholders can differ across systems. To address these variations, this package introduces a concept termed "flavor".
|
||||
|
||||
Currently, flavors such as `MySQL`, `PostgreSQL`, `SQLite`, `SQLServer`, `CQL`, `ClickHouse`, `Presto`, `Oracle` and `Informix` are supported. Should there be a demand for additional flavors, please submit an issue or a pull request.
|
||||
Currently, flavors such as `MySQL`, `PostgreSQL`, `SQLite`, `SQLServer`, `CQL`, `Datastore`, `Presto`, `Oracle` and `Informix` are supported. Should there be a demand for additional flavors, please submit an issue or a pull request.
|
||||
|
||||
By default, all builders utilize `DefaultFlavor` for SQL construction, with `MySQL` as the default setting.
|
||||
|
||||
|
||||
@@ -360,7 +360,7 @@ func (ctx *argsCompileContext) WriteValue(arg interface{}) {
|
||||
|
||||
default:
|
||||
switch ctx.Flavor {
|
||||
case MySQL, SQLite, CQL, ClickHouse, Presto, Informix, Doris:
|
||||
case MySQL, SQLite, CQL, Datastore, Presto, Informix, Doris:
|
||||
ctx.WriteRune('?')
|
||||
case PostgreSQL:
|
||||
fmt.Fprintf(ctx, "$%d", len(ctx.Values)+1)
|
||||
|
||||
+2
-2
@@ -98,9 +98,9 @@ func TestCreateTableGetFlavor(t *testing.T) {
|
||||
flavor := ctb.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ctbClick := ClickHouse.NewCreateTableBuilder()
|
||||
ctbClick := Datastore.NewCreateTableBuilder()
|
||||
flavor = ctbClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func TestCreateTableClone(t *testing.T) {
|
||||
|
||||
+4
-4
@@ -176,9 +176,9 @@ func TestCTEGetFlavor(t *testing.T) {
|
||||
flavor := cteb.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ctebClick := ClickHouse.NewCTEBuilder()
|
||||
ctebClick := Datastore.NewCTEBuilder()
|
||||
flavor = ctebClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func TestCTEQueryBuilderGetFlavor(t *testing.T) {
|
||||
@@ -189,9 +189,9 @@ func TestCTEQueryBuilderGetFlavor(t *testing.T) {
|
||||
flavor := ctetb.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ctetbClick := ClickHouse.NewCTEQueryBuilder()
|
||||
ctetbClick := Datastore.NewCTEQueryBuilder()
|
||||
flavor = ctetbClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func TestCTEBuildClone(t *testing.T) {
|
||||
|
||||
+3
-3
@@ -92,9 +92,9 @@ func TestDeleteBuilderGetFlavor(t *testing.T) {
|
||||
flavor := db.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
dbClick := ClickHouse.NewDeleteBuilder()
|
||||
dbClick := Datastore.NewDeleteBuilder()
|
||||
flavor = dbClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func ExampleDeleteBuilder_Returning() {
|
||||
@@ -134,7 +134,7 @@ func TestDeleteBuilderReturning(t *testing.T) {
|
||||
sql, _ = db.BuildWithFlavor(CQL)
|
||||
a.Equal("DELETE FROM user WHERE id = ?", sql)
|
||||
|
||||
sql, _ = db.BuildWithFlavor(ClickHouse)
|
||||
sql, _ = db.BuildWithFlavor(Datastore)
|
||||
a.Equal("DELETE FROM user WHERE id = ?", sql)
|
||||
|
||||
sql, _ = db.BuildWithFlavor(Presto)
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
SQLite
|
||||
SQLServer
|
||||
CQL
|
||||
ClickHouse
|
||||
Datastore
|
||||
Presto
|
||||
Oracle
|
||||
Informix
|
||||
@@ -57,8 +57,8 @@ func (f Flavor) String() string {
|
||||
return "SQLServer"
|
||||
case CQL:
|
||||
return "CQL"
|
||||
case ClickHouse:
|
||||
return "ClickHouse"
|
||||
case Datastore:
|
||||
return "Datastore"
|
||||
case Presto:
|
||||
return "Presto"
|
||||
case Oracle:
|
||||
@@ -89,8 +89,8 @@ func (f Flavor) Interpolate(sql string, args []interface{}) (string, error) {
|
||||
return sqlserverInterpolate(sql, args...)
|
||||
case CQL:
|
||||
return cqlInterpolate(sql, args...)
|
||||
case ClickHouse:
|
||||
return clickhouseInterpolate(sql, args...)
|
||||
case Datastore:
|
||||
return datastoreInterpolate(sql, args...)
|
||||
case Presto:
|
||||
return prestoInterpolate(sql, args...)
|
||||
case Oracle:
|
||||
@@ -167,7 +167,7 @@ func (f Flavor) NewCTEQueryBuilder() *CTEQueryBuilder {
|
||||
// - For PostgreSQL, SQL Server and SQLite, use double quote (") to quote name.
|
||||
func (f Flavor) Quote(name string) string {
|
||||
switch f {
|
||||
case MySQL, ClickHouse, Doris:
|
||||
case MySQL, Datastore, Doris:
|
||||
return fmt.Sprintf("`%s`", name)
|
||||
case PostgreSQL, SQLServer, SQLite, Presto, Oracle, Informix:
|
||||
return fmt.Sprintf(`"%s"`, name)
|
||||
@@ -195,7 +195,7 @@ func (f Flavor) PrepareInsertIgnore(table string, ib *InsertBuilder) {
|
||||
// see https://www.sqlite.org/lang_insert.html
|
||||
ib.verb = "INSERT OR IGNORE"
|
||||
|
||||
case ClickHouse, CQL, SQLServer, Presto, Informix, Doris:
|
||||
case Datastore, CQL, SQLServer, Presto, Informix, Doris:
|
||||
// All other databases do not support insert ignore
|
||||
ib.verb = "INSERT"
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ func TestFlavor(t *testing.T) {
|
||||
SQLite: "SQLite",
|
||||
SQLServer: "SQLServer",
|
||||
CQL: "CQL",
|
||||
ClickHouse: "ClickHouse",
|
||||
Datastore: "Datastore",
|
||||
Oracle: "Oracle",
|
||||
Informix: "Informix",
|
||||
Doris: "Doris",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module github.com/huandu/go-sqlbuilder
|
||||
module github.com/hanzoai/sqlbuilder
|
||||
|
||||
go 1.18
|
||||
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
|
||||
github.com/huandu/go-assert v1.1.6 h1:oaAfYxq9KNDi9qswn/6aE0EydfxSa+tWZC1KabNitYs=
|
||||
github.com/huandu/go-assert v1.1.6/go.mod h1:JuIfbmYG9ykwvuxoJ3V8TB5QP+3+ajIA54Y44TmkMxs=
|
||||
github.com/huandu/go-clone v1.7.3 h1:rtQODA+ABThEn6J5LBTppJfKmZy/FwfpMUWa8d01TTQ=
|
||||
github.com/huandu/go-clone v1.7.3/go.mod h1:ReGivhG6op3GYr+UY3lS6mxjKp7MIGTknuU5TbTVaXE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
+5
-5
@@ -132,8 +132,8 @@ func ExampleInsertBuilder_insertIgnore_sqlite() {
|
||||
// [1 Huan Du 1 2 Charmy Liu 1 1234567890]
|
||||
}
|
||||
|
||||
func ExampleInsertBuilder_insertIgnore_clickhouse() {
|
||||
ib := ClickHouse.NewInsertBuilder()
|
||||
func ExampleInsertBuilder_insertIgnore_datastore() {
|
||||
ib := Datastore.NewInsertBuilder()
|
||||
ib.InsertIgnoreInto("demo.user")
|
||||
ib.Cols("id", "name", "status", "created_at")
|
||||
ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))
|
||||
@@ -280,7 +280,7 @@ func TestInsertBuilderReturning(test *testing.T) {
|
||||
sql, _ = ib.BuildWithFlavor(CQL)
|
||||
a.Equal("INSERT INTO user (name) VALUES (?)", sql)
|
||||
|
||||
sql, _ = ib.BuildWithFlavor(ClickHouse)
|
||||
sql, _ = ib.BuildWithFlavor(Datastore)
|
||||
a.Equal("INSERT INTO user (name) VALUES (?)", sql)
|
||||
|
||||
sql, _ = ib.BuildWithFlavor(Presto)
|
||||
@@ -301,9 +301,9 @@ func TestInsertBuilderGetFlavor(t *testing.T) {
|
||||
flavor := ib.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ibClick := ClickHouse.NewInsertBuilder()
|
||||
ibClick := Datastore.NewInsertBuilder()
|
||||
flavor = ibClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func TestIssue200(t *testing.T) {
|
||||
|
||||
+4
-4
@@ -391,8 +391,8 @@ func cqlInterpolate(query string, args ...interface{}) (string, error) {
|
||||
return mysqlLikeInterpolate(CQL, query, args...)
|
||||
}
|
||||
|
||||
func clickhouseInterpolate(query string, args ...interface{}) (string, error) {
|
||||
return mysqlLikeInterpolate(ClickHouse, query, args...)
|
||||
func datastoreInterpolate(query string, args ...interface{}) (string, error) {
|
||||
return mysqlLikeInterpolate(Datastore, query, args...)
|
||||
}
|
||||
|
||||
func prestoInterpolate(query string, args ...interface{}) (string, error) {
|
||||
@@ -594,7 +594,7 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
|
||||
v = v.Add(500 * time.Nanosecond)
|
||||
|
||||
switch flavor {
|
||||
case MySQL, ClickHouse, Informix, Doris:
|
||||
case MySQL, Datastore, Informix, Doris:
|
||||
buf = append(buf, v.Format("'2006-01-02 15:04:05.999999'")...)
|
||||
|
||||
case PostgreSQL:
|
||||
@@ -734,7 +734,7 @@ func encodeValue(buf []byte, arg interface{}, flavor Flavor) ([]byte, error) {
|
||||
buf = append(buf, "0x"...)
|
||||
buf = appendHex(buf, data)
|
||||
|
||||
case ClickHouse:
|
||||
case Datastore:
|
||||
buf = append(buf, "unhex('"...)
|
||||
buf = appendHex(buf, data)
|
||||
buf = append(buf, "')"...)
|
||||
|
||||
+9
-9
@@ -195,47 +195,47 @@ func TestFlavorInterpolate(t *testing.T) {
|
||||
"", ErrInterpolateUnsupportedArgs,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT * FROM a WHERE name = ? AND state IN (?, ?, ?, ?, ?)", []interface{}{"I'm fine", 42, int8(8), int16(-16), int32(32), int64(64)},
|
||||
"SELECT * FROM a WHERE name = 'I\\'m fine' AND state IN (42, 8, -16, 32, 64)", nil,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT * FROM `a?` WHERE name = \"?\" AND state IN (?, '?', ?, ?, ?, ?, ?)", []interface{}{"\r\n\b\t\x1a\x00\\\"'", uint(42), uint8(8), uint16(16), uint32(32), uint64(64), "useless"},
|
||||
"SELECT * FROM `a?` WHERE name = \"?\" AND state IN ('\\r\\n\\b\\t\\Z\\0\\\\\\\"\\'', '?', 42, 8, 16, 32, 64)", nil,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?", []interface{}{true, false, float32(1.234567), 9.87654321, []byte(nil), []byte("I'm bytes"), dt, time.Time{}, nil},
|
||||
"SELECT TRUE, FALSE, 1.234567, 9.87654321, NULL, unhex('49276D206279746573'), '2019-04-24 12:23:34.123457', '0000-00-00', NULL", nil,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\?", []interface{}{MySQL},
|
||||
"SELECT '\\'?', \"\\\"?\", `\\`?`, \\'MySQL'", nil,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?", []interface{}{byteArr},
|
||||
"SELECT unhex('666F6F')", nil,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?", nil,
|
||||
"", ErrInterpolateMissingArgs,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?", []interface{}{complex(1, 2)},
|
||||
"", ErrInterpolateUnsupportedArgs,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?", []interface{}{[]complex128{complex(1, 2)}},
|
||||
"", ErrInterpolateUnsupportedArgs,
|
||||
},
|
||||
{
|
||||
ClickHouse,
|
||||
Datastore,
|
||||
"SELECT ?", []interface{}{errorValuer(1)},
|
||||
"", ErrErrorValuer,
|
||||
},
|
||||
|
||||
@@ -452,7 +452,7 @@ func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{
|
||||
}
|
||||
|
||||
switch flavor {
|
||||
case MySQL, SQLite, ClickHouse:
|
||||
case MySQL, SQLite, Datastore:
|
||||
if len(sb.limitVar) > 0 {
|
||||
buf.WriteLeadingString("LIMIT ")
|
||||
buf.WriteString(sb.limitVar)
|
||||
|
||||
+4
-4
@@ -144,7 +144,7 @@ func ExampleSelectBuilder_nestedJoin() {
|
||||
}
|
||||
|
||||
func ExampleSelectBuilder_limit_offset() {
|
||||
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle, Informix, Doris}
|
||||
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, Datastore, Presto, Oracle, Informix, Doris}
|
||||
results := make([][]string, len(flavors))
|
||||
sb := NewSelectBuilder()
|
||||
saveResults := func() {
|
||||
@@ -245,7 +245,7 @@ func ExampleSelectBuilder_limit_offset() {
|
||||
// #4: SELECT * FROM user LIMIT ?
|
||||
// #5: SELECT * FROM user ORDER BY id LIMIT ?
|
||||
//
|
||||
// ClickHouse
|
||||
// Datastore
|
||||
// #1: SELECT * FROM user
|
||||
// #2: SELECT * FROM user
|
||||
// #3: SELECT * FROM user LIMIT ? OFFSET ?
|
||||
@@ -413,9 +413,9 @@ func TestSelectBuilderGetFlavor(t *testing.T) {
|
||||
flavor := sb.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
sbClick := ClickHouse.NewSelectBuilder()
|
||||
sbClick := Datastore.NewSelectBuilder()
|
||||
flavor = sbClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func ExampleSelectBuilder_LateralAs() {
|
||||
|
||||
@@ -250,7 +250,7 @@ func (ub *UnionBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}
|
||||
}
|
||||
|
||||
switch flavor {
|
||||
case MySQL, SQLite, ClickHouse:
|
||||
case MySQL, SQLite, Datastore:
|
||||
if len(ub.limitVar) > 0 {
|
||||
buf.WriteLeadingString("LIMIT ")
|
||||
buf.WriteString(ub.limitVar)
|
||||
|
||||
+4
-4
@@ -100,13 +100,13 @@ func TestUnionBuilderGetFlavor(t *testing.T) {
|
||||
flavor := ub.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ubClick := ClickHouse.NewUnionBuilder()
|
||||
ubClick := Datastore.NewUnionBuilder()
|
||||
flavor = ubClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func ExampleUnionBuilder_limit_offset() {
|
||||
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle, Informix, Doris}
|
||||
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, Datastore, Presto, Oracle, Informix, Doris}
|
||||
results := make([][]string, len(flavors))
|
||||
|
||||
ub := NewUnionBuilder()
|
||||
@@ -210,7 +210,7 @@ func ExampleUnionBuilder_limit_offset() {
|
||||
// #4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?
|
||||
// #5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT ?
|
||||
//
|
||||
// ClickHouse
|
||||
// Datastore
|
||||
// #1: (SELECT * FROM user1) UNION (SELECT * FROM user2)
|
||||
// #2: (SELECT * FROM user1) UNION (SELECT * FROM user2)
|
||||
// #3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ? OFFSET ?
|
||||
|
||||
+4
-4
@@ -158,9 +158,9 @@ func TestUpdateBuilderGetFlavor(t *testing.T) {
|
||||
flavor := ub.Flavor()
|
||||
a.Equal(PostgreSQL, flavor)
|
||||
|
||||
ubClick := ClickHouse.NewUpdateBuilder()
|
||||
ubClick := Datastore.NewUpdateBuilder()
|
||||
flavor = ubClick.Flavor()
|
||||
a.Equal(ClickHouse, flavor)
|
||||
a.Equal(Datastore, flavor)
|
||||
}
|
||||
|
||||
func ExampleUpdateBuilder_Returning() {
|
||||
@@ -202,7 +202,7 @@ func TestUpdateBuilderReturning(t *testing.T) {
|
||||
sql, _ = ub.BuildWithFlavor(CQL)
|
||||
a.Equal("UPDATE user SET name = ? WHERE id = ?", sql)
|
||||
|
||||
sql, _ = ub.BuildWithFlavor(ClickHouse)
|
||||
sql, _ = ub.BuildWithFlavor(Datastore)
|
||||
a.Equal("UPDATE user SET name = ? WHERE id = ?", sql)
|
||||
|
||||
sql, _ = ub.BuildWithFlavor(Presto)
|
||||
@@ -307,7 +307,7 @@ func TestUpdateBuilderFrom(t *testing.T) {
|
||||
sql, _ = ub.BuildWithFlavor(CQL)
|
||||
a.Equal("UPDATE user SET name = ? WHERE id = ?", sql)
|
||||
|
||||
sql, _ = ub.BuildWithFlavor(ClickHouse)
|
||||
sql, _ = ub.BuildWithFlavor(Datastore)
|
||||
a.Equal("UPDATE user SET name = ? WHERE id = ?", sql)
|
||||
|
||||
sql, _ = ub.BuildWithFlavor(Presto)
|
||||
|
||||
Reference in New Issue
Block a user