diff --git a/catalog_test.go b/catalog_test.go new file mode 100644 index 00000000..2871026e --- /dev/null +++ b/catalog_test.go @@ -0,0 +1,190 @@ +package zetasql_test + +import ( + "testing" + + "github.com/goccy/go-zetasql" + "github.com/goccy/go-zetasql/resolved_ast" + "github.com/goccy/go-zetasql/types" +) + +type myCatalog struct { + simpleCatalog *types.SimpleCatalog + tables []types.Table + functions []*types.Function +} + +func (c *myCatalog) FullName() string { + return "catalog" +} + +func (c *myCatalog) FindTable(path []string) (types.Table, error) { + tableName := path[len(path)-1] + for _, table := range c.tables { + if table.Name() == tableName { + return table, nil + } + } + return nil, nil +} + +func (c *myCatalog) FindModel(path []string) (types.Model, error) { + return nil, nil +} + +func (c *myCatalog) FindConnection(path []string) (types.Connection, error) { + return nil, nil +} + +func (c *myCatalog) FindFunction(path []string) (*types.Function, error) { + funcName := path[len(path)-1] + for _, fn := range c.functions { + if fn.Name() == funcName { + return fn, nil + } + } + return c.simpleCatalog.FindFunction(path) +} + +func (c *myCatalog) FindTableValuedFunction(path []string) (types.TableValuedFunction, error) { + return nil, nil +} + +func (c *myCatalog) FindProcedure(path []string) (*types.Procedure, error) { + return nil, nil +} + +func (c *myCatalog) FindType(path []string) (types.Type, error) { + return nil, nil +} + +func (c *myCatalog) FindConstant(path []string) (types.Constant, error) { + return nil, nil +} + +func (c *myCatalog) FindConversion(from, to types.Type) (types.Conversion, error) { + return nil, nil +} + +func (c *myCatalog) ExtendedTypeSuperTypes(typ types.Type) (*types.TypeListView, error) { + return nil, nil +} + +func (c *myCatalog) SuggestTable(mistypedPath []string) string { + return "" +} + +func (c *myCatalog) SuggestModel(mistypedPath []string) string { + return "" +} + +func (c *myCatalog) SuggestFunction(mistypedPath []string) string { + return "" +} + +func (c *myCatalog) SuggestTableValuedFunction(mistypedPath []string) string { + return "" +} + +func (c *myCatalog) SuggestConstant(mistypedPath []string) string { + return "" +} + +type myTable struct { + name string + columns []types.Column +} + +func (t *myTable) Name() string { + return t.name +} + +func (t *myTable) FullName() string { + return t.name +} + +func (t *myTable) NumColumns() int { + return len(t.columns) +} + +func (t *myTable) Column(idx int) types.Column { + return t.columns[idx] +} + +func (t *myTable) PrimaryKey() []int { + return nil +} + +func (t *myTable) FindColumnByName(name string) types.Column { + return nil +} + +func (t *myTable) IsValueTable() bool { + return false +} + +func (t *myTable) SerializationID() int64 { + return 0 +} + +func (t *myTable) CreateEvaluatorTableIterator(columnIdxs []int) (*types.EvaluatorTableIterator, error) { + return nil, nil +} + +func (t *myTable) AnonymizationInfo() *types.AnonymizationInfo { + return nil +} + +func (t *myTable) SupportsAnonymization() bool { + return false +} + +func (t *myTable) TableTypeName(mode types.ProductMode) string { + return "" +} + +var ( + _ types.Catalog = &myCatalog{} + _ types.Table = &myTable{} +) + +func TestCatalog(t *testing.T) { + langOpt := zetasql.NewLanguageOptions() + langOpt.SetNameResolutionMode(zetasql.NameResolutionDefault) + langOpt.SetProductMode(types.ProductExternal) + langOpt.SetSupportedStatementKinds([]resolved_ast.Kind{resolved_ast.QueryStmt}) + opt := zetasql.NewAnalyzerOptions() + opt.SetAllowUndeclaredParameters(true) + opt.SetLanguage(langOpt) + + simpleCatalog := types.NewSimpleCatalog("simple") + simpleCatalog.AddZetaSQLBuiltinFunctions(langOpt.BuiltinFunctionOptions()) + catalog := &myCatalog{ + simpleCatalog: simpleCatalog, + tables: []types.Table{ + &myTable{ + name: "sample_table", + columns: []types.Column{ + types.NewSimpleColumn("sample_table", "col1", types.Int64Type()), + }, + }, + }, + functions: []*types.Function{ + types.NewFunction( + []string{"MY_FUNC"}, + "", + types.ScalarMode, + []*types.FunctionSignature{ + types.NewFunctionSignature( + types.NewFunctionArgumentType("", types.StringType()), + nil, + ), + }, + ), + }, + } + query := `SELECT * FROM sample_table WHERE MY_FUNC() = 'foo'` + if _, err := zetasql.AnalyzeStatement(query, catalog, opt); err != nil { + t.Fatal(err) + } +} diff --git a/internal/ccall/go-zetasql/bind.cc b/internal/ccall/go-zetasql/bind.cc index 8367e3a6..cbbbb98a 100644 --- a/internal/ccall/go-zetasql/bind.cc +++ b/internal/ccall/go-zetasql/bind.cc @@ -2,14 +2,17 @@ #define U_ICU_ENTRY_POINT_RENAME(x) GO_EXPORT(x) #include "go-zetasql/parser/parser/export.inc" #include "go-zetasql/public/analyzer/export.inc" +#include "go-zetasql/public/catalog/export.inc" #include "go-zetasql/public/simple_catalog/export.inc" #include "go-zetasql/public/sql_formatter/export.inc" #include "go-zetasql/parser/parser/bridge.h" #include "go-zetasql/public/analyzer/bridge.h" +#include "go-zetasql/public/catalog/bridge.h" #include "go-zetasql/public/simple_catalog/bridge.h" #include "go-zetasql/public/sql_formatter/bridge.h" #include "go-zetasql/parser/parser/bridge_cc.inc" #include "go-zetasql/public/analyzer/bridge_cc.inc" +#include "go-zetasql/public/catalog/bridge_cc.inc" #include "go-zetasql/public/simple_catalog/bridge_cc.inc" #include "go-zetasql/public/sql_formatter/bridge_cc.inc" @@ -18,6 +21,7 @@ extern "C" { #endif /* __cplusplus */ #include "go-zetasql/parser/parser/bridge.inc" #include "go-zetasql/public/analyzer/bridge.inc" +#include "go-zetasql/public/catalog/bridge.inc" #include "go-zetasql/public/simple_catalog/bridge.inc" #include "go-zetasql/public/sql_formatter/bridge.inc" diff --git a/internal/ccall/go-zetasql/bind_darwin.go b/internal/ccall/go-zetasql/bind_darwin.go index efe44cb7..46062c1a 100644 --- a/internal/ccall/go-zetasql/bind_darwin.go +++ b/internal/ccall/go-zetasql/bind_darwin.go @@ -26165,6 +26165,28 @@ func zetasql_ResolvedFunctionCallInfo_DebugString(arg0 unsafe.Pointer, arg1 *uns C.export_zetasql_ResolvedFunctionCallInfo_DebugString(arg0, arg1) } +func GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + zetasql_GoCatalog_new( + arg0, + arg1, + ) +} + +func zetasql_GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_GoCatalog_new(arg0, arg1) +} + +func GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + zetasql_GoTable_new( + arg0, + arg1, + ) +} + +func zetasql_GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_GoTable_new(arg0, arg1) +} + func Type_Kind(arg0 unsafe.Pointer, arg1 *int) { zetasql_Type_Kind( arg0, diff --git a/internal/ccall/go-zetasql/bind_linux.go b/internal/ccall/go-zetasql/bind_linux.go index 76139ba7..08e6fa7e 100644 --- a/internal/ccall/go-zetasql/bind_linux.go +++ b/internal/ccall/go-zetasql/bind_linux.go @@ -26168,6 +26168,28 @@ func zetasql_ResolvedFunctionCallInfo_DebugString(arg0 unsafe.Pointer, arg1 *uns C.export_zetasql_ResolvedFunctionCallInfo_DebugString(arg0, arg1) } +func GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + zetasql_GoCatalog_new( + arg0, + arg1, + ) +} + +func zetasql_GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_GoCatalog_new(arg0, arg1) +} + +func GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + zetasql_GoTable_new( + arg0, + arg1, + ) +} + +func zetasql_GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_GoTable_new(arg0, arg1) +} + func Type_Kind(arg0 unsafe.Pointer, arg1 *int) { zetasql_Type_Kind( arg0, diff --git a/internal/ccall/go-zetasql/bridge.h b/internal/ccall/go-zetasql/bridge.h index a9610112..ef08fe0f 100644 --- a/internal/ccall/go-zetasql/bridge.h +++ b/internal/ccall/go-zetasql/bridge.h @@ -8,6 +8,7 @@ extern "C" { #include #include "../go-zetasql/parser/parser/bridge_extern.h" #include "../go-zetasql/public/analyzer/bridge_extern.h" +#include "../go-zetasql/public/catalog/bridge_extern.h" #include "../go-zetasql/public/simple_catalog/bridge_extern.h" #include "../go-zetasql/public/sql_formatter/bridge_extern.h" diff --git a/internal/ccall/go-zetasql/callback_darwin.go b/internal/ccall/go-zetasql/callback_darwin.go new file mode 100644 index 00000000..def820ee --- /dev/null +++ b/internal/ccall/go-zetasql/callback_darwin.go @@ -0,0 +1,397 @@ +package zetasql + +/* +#cgo CXXFLAGS: -std=c++1z +#cgo CXXFLAGS: -I../ +#cgo CXXFLAGS: -I../protobuf +#cgo CXXFLAGS: -I../gtest +#cgo CXXFLAGS: -I../icu +#cgo CXXFLAGS: -I../re2 +#cgo CXXFLAGS: -I../json +#cgo CXXFLAGS: -I../googleapis +#cgo CXXFLAGS: -I../flex/src +#cgo CXXFLAGS: -Wno-char-subscripts +#cgo CXXFLAGS: -Wno-sign-compare +#cgo CXXFLAGS: -Wno-switch +#cgo CXXFLAGS: -Wno-unused-function +#cgo CXXFLAGS: -Wno-deprecated-declarations +#cgo CXXFLAGS: -Wno-inconsistent-missing-override +#cgo CXXFLAGS: -Wno-unknown-attributes +#cgo CXXFLAGS: -Wno-macro-redefined +#cgo CXXFLAGS: -Wno-shift-count-overflow +#cgo CXXFLAGS: -Wno-enum-compare-switch +#cgo CXXFLAGS: -Wno-return-type +#cgo CXXFLAGS: -Wno-subobject-linkage +#cgo CXXFLAGS: -Wno-unknown-warning-option +#cgo CXXFLAGS: -DHAVE_PTHREAD +#cgo CXXFLAGS: -DU_COMMON_IMPLEMENTATION + +#define GO_EXPORT(API) export_zetasql_ ## API +#include "bridge.h" +#include "../go-absl/time/go_internal/cctz/time_zone/bridge.h" +*/ +import "C" +import ( + "reflect" + "runtime/cgo" + "unsafe" + + _ "github.com/goccy/go-zetasql/internal/ccall/go-absl/time/go_internal/cctz/time_zone" +) + +type GoCatalog struct { + FullName func() string + FindTable func([]string) (unsafe.Pointer, error) + FindModel func([]string) (unsafe.Pointer, error) + FindConnection func([]string) (unsafe.Pointer, error) + FindFunction func([]string) (unsafe.Pointer, error) + FindTableValuedFunction func([]string) (unsafe.Pointer, error) + FindProcedure func([]string) (unsafe.Pointer, error) + FindType func([]string) (unsafe.Pointer, error) + FindConstant func([]string) (unsafe.Pointer, error) + FindConversion func(unsafe.Pointer, unsafe.Pointer) (unsafe.Pointer, error) + ExtendedTypeSuperTypes func(unsafe.Pointer) (unsafe.Pointer, error) + SuggestTable func([]string) string + SuggestModel func([]string) string + SuggestFunction func([]string) string + SuggestTableValuedFunction func([]string) string + SuggestConstant func([]string) string +} + +type GoTable struct { + Name func() string + FullName func() string + NumColumns func() int + Column func(int) unsafe.Pointer + PrimaryKey func() []int + FindColumnByName func(name string) unsafe.Pointer + IsValueTable func() bool + SerializationID func() int64 + CreateEvaluatorTableIterator func(columnIdxs []int) (unsafe.Pointer, error) + AnonymizationInfo func() unsafe.Pointer + SupportsAnonymization func() bool + TableTypeName func(int) string +} + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +func ptrToSlice(p unsafe.Pointer, cb func(unsafe.Pointer)) { + slice := (*reflect.SliceHeader)(p) + for i := 0; i < slice.Len; i++ { + cb(*(*unsafe.Pointer)(unsafe.Pointer(slice.Data + uintptr(i)*uintptrSize))) + } +} + +//export GoCatalog_FullName +func GoCatalog_FullName(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + return C.CString(cat.FullName()) +} + +//export GoCatalog_FindTable +func GoCatalog_FindTable(v unsafe.Pointer, pathPtr unsafe.Pointer, table *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + tablePtr, err := cat.FindTable(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *table = tablePtr + } +} + +//export GoCatalog_FindModel +func GoCatalog_FindModel(v unsafe.Pointer, pathPtr unsafe.Pointer, model *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + modelPtr, err := cat.FindModel(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *model = modelPtr + } +} + +//export GoCatalog_FindConnection +func GoCatalog_FindConnection(v unsafe.Pointer, pathPtr unsafe.Pointer, conn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + connPtr, err := cat.FindConnection(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *conn = connPtr + } +} + +//export GoCatalog_FindFunction +func GoCatalog_FindFunction(v unsafe.Pointer, pathPtr unsafe.Pointer, fn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + fnPtr, err := cat.FindFunction(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *fn = fnPtr + } +} + +//export GoCatalog_FindTableValuedFunction +func GoCatalog_FindTableValuedFunction(v unsafe.Pointer, pathPtr unsafe.Pointer, fn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + fnPtr, err := cat.FindTableValuedFunction(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *fn = fnPtr + } +} + +//export GoCatalog_FindProcedure +func GoCatalog_FindProcedure(v unsafe.Pointer, pathPtr unsafe.Pointer, proc *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + procPtr, err := cat.FindProcedure(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *proc = procPtr + } +} + +//export GoCatalog_FindType +func GoCatalog_FindType(v unsafe.Pointer, pathPtr unsafe.Pointer, typ *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + typPtr, err := cat.FindType(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *typ = typPtr + } +} + +//export GoCatalog_FindConstant +func GoCatalog_FindConstant(v unsafe.Pointer, pathPtr unsafe.Pointer, constant *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + consPtr, err := cat.FindConstant(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *constant = consPtr + } +} + +//export GoCatalog_FindConversion +func GoCatalog_FindConversion(v unsafe.Pointer, from unsafe.Pointer, to unsafe.Pointer, conv *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + convPtr, err := cat.FindConversion(from, to) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *conv = convPtr + } +} + +//export GoCatalog_ExtendedTypeSuperTypes +func GoCatalog_ExtendedTypeSuperTypes(v unsafe.Pointer, typ unsafe.Pointer, list *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + listPtr, err := cat.ExtendedTypeSuperTypes(typ) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *list = listPtr + } +} + +//export GoCatalog_SuggestTable +func GoCatalog_SuggestTable(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestTable(path)) +} + +//export GoCatalog_SuggestModel +func GoCatalog_SuggestModel(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestModel(path)) +} + +//export GoCatalog_SuggestFunction +func GoCatalog_SuggestFunction(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestFunction(path)) +} + +//export GoCatalog_SuggestTableValuedFunction +func GoCatalog_SuggestTableValuedFunction(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestTableValuedFunction(path)) +} + +//export GoCatalog_SuggestConstant +func GoCatalog_SuggestConstant(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestConstant(path)) +} + +//export GoTable_Name +func GoTable_Name(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.Name()) +} + +//export GoTable_FullName +func GoTable_FullName(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.FullName()) +} + +//export GoTable_NumColumns +func GoTable_NumColumns(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.int(table.NumColumns()) +} + +//export GoTable_Column +func GoTable_Column(v unsafe.Pointer, idx C.int) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.Column(int(idx)) +} + +//export GoTable_PrimaryKey +func GoTable_PrimaryKey(v unsafe.Pointer) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + keys := table.PrimaryKey() + return unsafe.Pointer(&keys) +} + +//export GoTable_FindColumnByName +func GoTable_FindColumnByName(v unsafe.Pointer, name *C.char) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.FindColumnByName(C.GoString(name)) +} + +//export GoTable_IsValueTable +func GoTable_IsValueTable(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + if table.IsValueTable() { + return 0 + } + return 1 +} + +//export GoTable_SerializationID +func GoTable_SerializationID(v unsafe.Pointer) C.int64_t { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.int64_t(table.SerializationID()) +} + +//export GoTable_CreateEvaluatorTableIterator +func GoTable_CreateEvaluatorTableIterator(v unsafe.Pointer, columnIdxsPtr unsafe.Pointer, iter *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + var idxs []int + ptrToSlice(columnIdxsPtr, func(p unsafe.Pointer) { + idxs = append(idxs, int(uintptr(p))) + }) + iterPtr, err := table.CreateEvaluatorTableIterator(idxs) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *iter = iterPtr + } +} + +//export GoTable_AnonymizationInfo +func GoTable_AnonymizationInfo(v unsafe.Pointer) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.AnonymizationInfo() +} + +//export GoTable_SupportsAnonymization +func GoTable_SupportsAnonymization(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + if table.SupportsAnonymization() { + return 0 + } + return 1 +} + +//export GoTable_TableTypeName +func GoTable_TableTypeName(v unsafe.Pointer, mode C.int) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.TableTypeName(int(mode))) +} diff --git a/internal/ccall/go-zetasql/callback_linux.go b/internal/ccall/go-zetasql/callback_linux.go new file mode 100644 index 00000000..fe94eeec --- /dev/null +++ b/internal/ccall/go-zetasql/callback_linux.go @@ -0,0 +1,398 @@ +package zetasql + +/* +#cgo CXXFLAGS: -std=c++1z +#cgo CXXFLAGS: -I../ +#cgo CXXFLAGS: -I../protobuf +#cgo CXXFLAGS: -I../gtest +#cgo CXXFLAGS: -I../icu +#cgo CXXFLAGS: -I../re2 +#cgo CXXFLAGS: -I../json +#cgo CXXFLAGS: -I../googleapis +#cgo CXXFLAGS: -I../flex/src +#cgo CXXFLAGS: -Wno-char-subscripts +#cgo CXXFLAGS: -Wno-sign-compare +#cgo CXXFLAGS: -Wno-switch +#cgo CXXFLAGS: -Wno-unused-function +#cgo CXXFLAGS: -Wno-deprecated-declarations +#cgo CXXFLAGS: -Wno-inconsistent-missing-override +#cgo CXXFLAGS: -Wno-unknown-attributes +#cgo CXXFLAGS: -Wno-macro-redefined +#cgo CXXFLAGS: -Wno-shift-count-overflow +#cgo CXXFLAGS: -Wno-enum-compare-switch +#cgo CXXFLAGS: -Wno-return-type +#cgo CXXFLAGS: -Wno-subobject-linkage +#cgo CXXFLAGS: -Wno-unknown-warning-option +#cgo CXXFLAGS: -DHAVE_PTHREAD +#cgo CXXFLAGS: -DU_COMMON_IMPLEMENTATION +#cgo LDFLAGS: -ldl + +#define GO_EXPORT(API) export_zetasql_ ## API +#include "bridge.h" +#include "../go-absl/time/go_internal/cctz/time_zone/bridge.h" +*/ +import "C" +import ( + "reflect" + "runtime/cgo" + "unsafe" + + _ "github.com/goccy/go-zetasql/internal/ccall/go-absl/time/go_internal/cctz/time_zone" +) + +type GoCatalog struct { + FullName func() string + FindTable func([]string) (unsafe.Pointer, error) + FindModel func([]string) (unsafe.Pointer, error) + FindConnection func([]string) (unsafe.Pointer, error) + FindFunction func([]string) (unsafe.Pointer, error) + FindTableValuedFunction func([]string) (unsafe.Pointer, error) + FindProcedure func([]string) (unsafe.Pointer, error) + FindType func([]string) (unsafe.Pointer, error) + FindConstant func([]string) (unsafe.Pointer, error) + FindConversion func(unsafe.Pointer, unsafe.Pointer) (unsafe.Pointer, error) + ExtendedTypeSuperTypes func(unsafe.Pointer) (unsafe.Pointer, error) + SuggestTable func([]string) string + SuggestModel func([]string) string + SuggestFunction func([]string) string + SuggestTableValuedFunction func([]string) string + SuggestConstant func([]string) string +} + +type GoTable struct { + Name func() string + FullName func() string + NumColumns func() int + Column func(int) unsafe.Pointer + PrimaryKey func() []int + FindColumnByName func(name string) unsafe.Pointer + IsValueTable func() bool + SerializationID func() int64 + CreateEvaluatorTableIterator func(columnIdxs []int) (unsafe.Pointer, error) + AnonymizationInfo func() unsafe.Pointer + SupportsAnonymization func() bool + TableTypeName func(int) string +} + +const uintptrSize = 4 << (^uintptr(0) >> 63) + +func ptrToSlice(p unsafe.Pointer, cb func(unsafe.Pointer)) { + slice := (*reflect.SliceHeader)(p) + for i := 0; i < slice.Len; i++ { + cb(*(*unsafe.Pointer)(unsafe.Pointer(slice.Data + uintptr(i)*uintptrSize))) + } +} + +//export GoCatalog_FullName +func GoCatalog_FullName(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + return C.CString(cat.FullName()) +} + +//export GoCatalog_FindTable +func GoCatalog_FindTable(v unsafe.Pointer, pathPtr unsafe.Pointer, table *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + tablePtr, err := cat.FindTable(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *table = tablePtr + } +} + +//export GoCatalog_FindModel +func GoCatalog_FindModel(v unsafe.Pointer, pathPtr unsafe.Pointer, model *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + modelPtr, err := cat.FindModel(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *model = modelPtr + } +} + +//export GoCatalog_FindConnection +func GoCatalog_FindConnection(v unsafe.Pointer, pathPtr unsafe.Pointer, conn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + connPtr, err := cat.FindConnection(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *conn = connPtr + } +} + +//export GoCatalog_FindFunction +func GoCatalog_FindFunction(v unsafe.Pointer, pathPtr unsafe.Pointer, fn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + fnPtr, err := cat.FindFunction(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *fn = fnPtr + } +} + +//export GoCatalog_FindTableValuedFunction +func GoCatalog_FindTableValuedFunction(v unsafe.Pointer, pathPtr unsafe.Pointer, fn *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + fnPtr, err := cat.FindTableValuedFunction(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *fn = fnPtr + } +} + +//export GoCatalog_FindProcedure +func GoCatalog_FindProcedure(v unsafe.Pointer, pathPtr unsafe.Pointer, proc *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + procPtr, err := cat.FindProcedure(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *proc = procPtr + } +} + +//export GoCatalog_FindType +func GoCatalog_FindType(v unsafe.Pointer, pathPtr unsafe.Pointer, typ *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + typPtr, err := cat.FindType(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *typ = typPtr + } +} + +//export GoCatalog_FindConstant +func GoCatalog_FindConstant(v unsafe.Pointer, pathPtr unsafe.Pointer, constant *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + consPtr, err := cat.FindConstant(path) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *constant = consPtr + } +} + +//export GoCatalog_FindConversion +func GoCatalog_FindConversion(v unsafe.Pointer, from unsafe.Pointer, to unsafe.Pointer, conv *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + convPtr, err := cat.FindConversion(from, to) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *conv = convPtr + } +} + +//export GoCatalog_ExtendedTypeSuperTypes +func GoCatalog_ExtendedTypeSuperTypes(v unsafe.Pointer, typ unsafe.Pointer, list *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + listPtr, err := cat.ExtendedTypeSuperTypes(typ) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *list = listPtr + } +} + +//export GoCatalog_SuggestTable +func GoCatalog_SuggestTable(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestTable(path)) +} + +//export GoCatalog_SuggestModel +func GoCatalog_SuggestModel(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestModel(path)) +} + +//export GoCatalog_SuggestFunction +func GoCatalog_SuggestFunction(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestFunction(path)) +} + +//export GoCatalog_SuggestTableValuedFunction +func GoCatalog_SuggestTableValuedFunction(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestTableValuedFunction(path)) +} + +//export GoCatalog_SuggestConstant +func GoCatalog_SuggestConstant(v unsafe.Pointer, pathPtr unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + cat := h.Value().(*GoCatalog) + var path []string + ptrToSlice(pathPtr, func(p unsafe.Pointer) { + path = append(path, C.GoString((*C.char)(p))) + }) + return C.CString(cat.SuggestConstant(path)) +} + +//export GoTable_Name +func GoTable_Name(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.Name()) +} + +//export GoTable_FullName +func GoTable_FullName(v unsafe.Pointer) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.FullName()) +} + +//export GoTable_NumColumns +func GoTable_NumColumns(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.int(table.NumColumns()) +} + +//export GoTable_Column +func GoTable_Column(v unsafe.Pointer, idx C.int) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.Column(int(idx)) +} + +//export GoTable_PrimaryKey +func GoTable_PrimaryKey(v unsafe.Pointer) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + keys := table.PrimaryKey() + return unsafe.Pointer(&keys) +} + +//export GoTable_FindColumnByName +func GoTable_FindColumnByName(v unsafe.Pointer, name *C.char) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.FindColumnByName(C.GoString(name)) +} + +//export GoTable_IsValueTable +func GoTable_IsValueTable(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + if table.IsValueTable() { + return 0 + } + return 1 +} + +//export GoTable_SerializationID +func GoTable_SerializationID(v unsafe.Pointer) C.int64_t { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.int64_t(table.SerializationID()) +} + +//export GoTable_CreateEvaluatorTableIterator +func GoTable_CreateEvaluatorTableIterator(v unsafe.Pointer, columnIdxsPtr unsafe.Pointer, iter *unsafe.Pointer, ret **C.char) { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + var idxs []int + ptrToSlice(columnIdxsPtr, func(p unsafe.Pointer) { + idxs = append(idxs, int(uintptr(p))) + }) + iterPtr, err := table.CreateEvaluatorTableIterator(idxs) + if err != nil { + *ret = C.CString(err.Error()) + } else { + *iter = iterPtr + } +} + +//export GoTable_AnonymizationInfo +func GoTable_AnonymizationInfo(v unsafe.Pointer) unsafe.Pointer { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return table.AnonymizationInfo() +} + +//export GoTable_SupportsAnonymization +func GoTable_SupportsAnonymization(v unsafe.Pointer) C.int { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + if table.SupportsAnonymization() { + return 0 + } + return 1 +} + +//export GoTable_TableTypeName +func GoTable_TableTypeName(v unsafe.Pointer, mode C.int) *C.char { + h := *(*cgo.Handle)(v) + table := h.Value().(*GoTable) + return C.CString(table.TableTypeName(int(mode))) +} diff --git a/internal/ccall/go-zetasql/public/catalog/bind_darwin.go b/internal/ccall/go-zetasql/public/catalog/bind_darwin.go index af4bf658..fee16571 100644 --- a/internal/ccall/go-zetasql/public/catalog/bind_darwin.go +++ b/internal/ccall/go-zetasql/public/catalog/bind_darwin.go @@ -36,6 +36,28 @@ import ( "unsafe" ) +func GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + catalog_GoCatalog_new( + arg0, + arg1, + ) +} + +func catalog_GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_public_catalog_GoCatalog_new(arg0, arg1) +} + +func GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + catalog_GoTable_new( + arg0, + arg1, + ) +} + +func catalog_GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_public_catalog_GoTable_new(arg0, arg1) +} + //export export_zetasql_public_catalog_cctz_FixedOffsetFromName //go:linkname export_zetasql_public_catalog_cctz_FixedOffsetFromName github.com/goccy/go-zetasql/internal/ccall/go-absl/time/go_internal/cctz/time_zone.time_zone_cctz_FixedOffsetFromName func export_zetasql_public_catalog_cctz_FixedOffsetFromName(arg0 unsafe.Pointer, arg1 unsafe.Pointer, arg2 *C.char) diff --git a/internal/ccall/go-zetasql/public/catalog/bind_linux.go b/internal/ccall/go-zetasql/public/catalog/bind_linux.go index be4bc55b..86330f78 100644 --- a/internal/ccall/go-zetasql/public/catalog/bind_linux.go +++ b/internal/ccall/go-zetasql/public/catalog/bind_linux.go @@ -39,6 +39,28 @@ import ( "unsafe" ) +func GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + catalog_GoCatalog_new( + arg0, + arg1, + ) +} + +func catalog_GoCatalog_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_public_catalog_GoCatalog_new(arg0, arg1) +} + +func GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + catalog_GoTable_new( + arg0, + arg1, + ) +} + +func catalog_GoTable_new(arg0 unsafe.Pointer, arg1 *unsafe.Pointer) { + C.export_zetasql_public_catalog_GoTable_new(arg0, arg1) +} + //export export_zetasql_public_catalog_cctz_FixedOffsetFromName //go:linkname export_zetasql_public_catalog_cctz_FixedOffsetFromName github.com/goccy/go-zetasql/internal/ccall/go-absl/time/go_internal/cctz/time_zone.time_zone_cctz_FixedOffsetFromName func export_zetasql_public_catalog_cctz_FixedOffsetFromName(arg0 unsafe.Pointer, arg1 unsafe.Pointer, arg2 *C.char) diff --git a/internal/ccall/go-zetasql/public/catalog/bridge.inc b/internal/ccall/go-zetasql/public/catalog/bridge.inc index e69de29b..37be8220 100644 --- a/internal/ccall/go-zetasql/public/catalog/bridge.inc +++ b/internal/ccall/go-zetasql/public/catalog/bridge.inc @@ -0,0 +1,407 @@ +#include "_cgo_export.h" + +using namespace zetasql; + +class GoCatalog : public Catalog { +public: + GoCatalog(void *go_catalog_ptr) : go_catalog_ptr(go_catalog_ptr) {} + ~GoCatalog() {} + + std::string FullName() const { + return std::string(GoCatalog_FullName(this->go_catalog_ptr)); + } + + absl::Status FindTable(const absl::Span& path, const Table** table, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("Table"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *tableV = nullptr; + char *ret = nullptr; + GoCatalog_FindTable(this->go_catalog_ptr, (void *)path_slice, &tableV, &ret); + if (tableV == nullptr) { + return TableNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *table = (const Table *)tableV; + return absl::OkStatus(); + } + + absl::Status FindModel(const absl::Span& path, const Model** model, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("Model"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *modelV = nullptr; + char *ret = nullptr; + GoCatalog_FindModel(this->go_catalog_ptr, (void *)path_slice, &modelV, &ret); + if (modelV == nullptr) { + return ModelNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *model = (const Model *)modelV; + return absl::OkStatus(); + } + + absl::Status FindConnection(const absl::Span& path, const Connection** connection, const FindOptions& options) { + if (path.empty()) { + return EmptyNamePathInternalError("Connection"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *connV = nullptr; + char *ret = nullptr; + GoCatalog_FindConnection(this->go_catalog_ptr, (void *)path_slice, &connV, &ret); + if (connV == nullptr) { + return ConnectionNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *connection = (const Connection *)connV; + return absl::OkStatus(); + } + + absl::Status FindFunction(const absl::Span& path, const Function** function, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("Function"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *funcV = nullptr; + char *ret = nullptr; + GoCatalog_FindFunction(this->go_catalog_ptr, (void *)path_slice, &funcV, &ret); + if (funcV == nullptr) { + return FunctionNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *function = (const Function *)funcV; + return absl::OkStatus(); + } + + absl::Status FindTableValuedFunction(const absl::Span& path, const TableValuedFunction** function, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("TableValuedFunction"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *funcV = nullptr; + char *ret = nullptr; + GoCatalog_FindTableValuedFunction(this->go_catalog_ptr, (void *)path_slice, &funcV, &ret); + if (funcV == nullptr) { + return TableValuedFunctionNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *function = (const TableValuedFunction *)funcV; + return absl::OkStatus(); + } + + absl::Status FindProcedure(const absl::Span& path, const Procedure** procedure, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("Procedure"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *procV = nullptr; + char *ret = nullptr; + GoCatalog_FindProcedure(this->go_catalog_ptr, (void *)path_slice, &procV, &ret); + if (procV == nullptr) { + return ProcedureNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *procedure = (const Procedure *)procV; + return absl::OkStatus(); + } + + absl::Status FindType(const absl::Span& path, const Type** type, const FindOptions& options = FindOptions()) { + if (path.empty()) { + return EmptyNamePathInternalError("Type"); + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * path.size()); + for (size_t i = 0; i < path.size(); i++) { + data[i] = path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = path.size(); + path_slice->cap = path.size(); + + void *typeV = nullptr; + char *ret = nullptr; + GoCatalog_FindType(this->go_catalog_ptr, (void *)path_slice, &typeV, &ret); + if (typeV == nullptr) { + return TypeNotFoundError(path); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *type = (const Type *)typeV; + return absl::OkStatus(); + } + + absl::Status FindConstantWithPathPrefix(const absl::Span path, int* num_names_consumed, const Constant** constant, const FindOptions& options = FindOptions()) { + return absl::OkStatus(); + } + + absl::Status FindConversion(const Type* from_type, const Type* to_type, const FindConversionOptions& options, Conversion* conversion) { + void *convV = nullptr; + char *ret = nullptr; + GoCatalog_FindConversion(this->go_catalog_ptr, (void *)from_type, (void *)to_type, &convV, &ret); + if (convV == nullptr) { + return ConversionNotFoundError(from_type, to_type, options); + } + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + *conversion = *(Conversion *)convV; + return absl::OkStatus(); + } + + absl::StatusOr GetExtendedTypeSuperTypes(const Type* type) { + void *listV = nullptr; + char *ret = nullptr; + GoCatalog_ExtendedTypeSuperTypes(this->go_catalog_ptr, (void *)type, &listV, &ret); + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + return *(TypeListView *)listV; + } + + std::string SuggestTable(const absl::Span& mistyped_path) { + if (mistyped_path.empty()) { + return ""; + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * mistyped_path.size()); + for (size_t i = 0; i < mistyped_path.size(); i++) { + data[i] = mistyped_path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = mistyped_path.size(); + path_slice->cap = mistyped_path.size(); + + return std::string(GoCatalog_SuggestTable(this->go_catalog_ptr, (void *)path_slice)); + } + + std::string SuggestModel(const absl::Span& mistyped_path) { + if (mistyped_path.empty()) { + return ""; + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * mistyped_path.size()); + for (size_t i = 0; i < mistyped_path.size(); i++) { + data[i] = mistyped_path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = mistyped_path.size(); + path_slice->cap = mistyped_path.size(); + + return std::string(GoCatalog_SuggestModel(this->go_catalog_ptr, (void *)path_slice)); + } + + std::string SuggestFunction(const absl::Span& mistyped_path) { + if (mistyped_path.empty()) { + return ""; + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * mistyped_path.size()); + for (size_t i = 0; i < mistyped_path.size(); i++) { + data[i] = mistyped_path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = mistyped_path.size(); + path_slice->cap = mistyped_path.size(); + + return std::string(GoCatalog_SuggestFunction(this->go_catalog_ptr, (void *)path_slice)); + } + + std::string SuggestTableValuedFunction(const absl::Span& mistyped_path) { + if (mistyped_path.empty()) { + return ""; + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * mistyped_path.size()); + for (size_t i = 0; i < mistyped_path.size(); i++) { + data[i] = mistyped_path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = mistyped_path.size(); + path_slice->cap = mistyped_path.size(); + + return std::string(GoCatalog_SuggestTableValuedFunction(this->go_catalog_ptr, (void *)path_slice)); + } + + std::string SuggestConstant(const absl::Span& mistyped_path) { + if (mistyped_path.empty()) { + return ""; + } + GoSlice *path_slice = (GoSlice *)malloc(sizeof(GoSlice)); + const char **data = (const char **)malloc(sizeof(void *) * mistyped_path.size()); + for (size_t i = 0; i < mistyped_path.size(); i++) { + data[i] = mistyped_path[i].c_str(); + } + path_slice->data = (void *)data; + path_slice->len = mistyped_path.size(); + path_slice->cap = mistyped_path.size(); + + return std::string(GoCatalog_SuggestConstant(this->go_catalog_ptr, (void *)path_slice)); + } + +private: + void *go_catalog_ptr; +}; + +class GoTable : public Table { +public: + GoTable(void *go_table_ptr) : go_table_ptr(go_table_ptr) {} + ~GoTable() {} + + std::string Name() const { + return std::string(GoTable_Name(this->go_table_ptr)); + } + + std::string FullName() const { + return std::string(GoTable_FullName(this->go_table_ptr)); + } + + int NumColumns() const { + return GoTable_NumColumns(this->go_table_ptr); + } + + const Column* GetColumn(int i) const { + return (Column *)GoTable_Column(this->go_table_ptr, i); + } + + std::optional> PrimaryKey() const { + GoSlice *ret = (GoSlice *)GoTable_PrimaryKey(this->go_table_ptr); + std::vector keys; + int **data = (int **)ret->data; + for (int i = 0; i < ret->len; i++) { + keys.push_back(*data[i]); + } + return keys; + } + + const Column* FindColumnByName(const std::string& name) const { + return (Column *)GoTable_FindColumnByName(this->go_table_ptr, (char *)name.c_str()); + } + + bool IsValueTable() const { + if (GoTable_IsValueTable(this->go_table_ptr) == 1) { + return true; + } + return false; + } + + int64_t GetSerializationId() const { + return GoTable_SerializationID(this->go_table_ptr); + } + + absl::StatusOr> CreateEvaluatorTableIterator(absl::Span column_idxs) const { + GoSlice *idxs_slice = (GoSlice *)malloc(sizeof(GoSlice)); + int64_t *data = (int64_t *)malloc(sizeof(int64_t) * column_idxs.size()); + for (size_t i = 0; i < column_idxs.size(); i++) { + data[i] = column_idxs[i]; + } + idxs_slice->data = (void *)data; + idxs_slice->len = column_idxs.size(); + idxs_slice->cap = column_idxs.size(); + + void *iter = nullptr; + char *ret = nullptr; + GoTable_CreateEvaluatorTableIterator(this->go_table_ptr, (void *)idxs_slice, &iter, &ret); + + if (ret != nullptr) { + return absl::InvalidArgumentError(ret); + } + std::unique_ptr v((EvaluatorTableIterator *)iter); + return v; + } + + std::optional GetAnonymizationInfo() const { + AnonymizationInfo *ret = (AnonymizationInfo *)GoTable_AnonymizationInfo(this->go_table_ptr); + if (ret == nullptr) { + return std::nullopt; + } + return *ret; + } + + bool SupportsAnonymization() const { + if (GoTable_SupportsAnonymization(this->go_table_ptr) == 1) { + return true; + } + return false; + } + + std::string GetTableTypeName(ProductMode mode) const { + return std::string(GoTable_TableTypeName(this->go_table_ptr, int(mode))); + } + +private: + void *go_table_ptr; +}; + + +void GO_EXPORT(GoCatalog_new)(void * arg0,void ** arg1) +{ + *arg1 = (void *)(new GoCatalog(arg0)); +} + +void GO_EXPORT(GoTable_new)(void * arg0,void ** arg1) +{ + *arg1 = (void *)(new GoTable(arg0)); +} diff --git a/internal/ccall/go-zetasql/public/catalog/bridge_extern.h b/internal/ccall/go-zetasql/public/catalog/bridge_extern.h index 8b137891..84907898 100644 --- a/internal/ccall/go-zetasql/public/catalog/bridge_extern.h +++ b/internal/ccall/go-zetasql/public/catalog/bridge_extern.h @@ -1 +1,3 @@ +extern void GO_EXPORT(GoCatalog_new)(void * arg0,void ** arg1); +extern void GO_EXPORT(GoTable_new)(void * arg0,void ** arg1); diff --git a/internal/cmd/generator/bridge.yaml b/internal/cmd/generator/bridge.yaml index 37fa0a4e..b7cba34c 100644 --- a/internal/cmd/generator/bridge.yaml +++ b/internal/cmd/generator/bridge.yaml @@ -4726,6 +4726,20 @@ - struct ret: - struct + +- package: zetasql/public/catalog + methods: + - name: GoCatalog_new + args: + - struct + ret: + - struct + - name: GoTable_new + args: + - struct + ret: + - struct + - package: zetasql/public/simple_catalog methods: - name: Type_Kind diff --git a/types/catalog.go b/types/catalog.go index 999d8c13..74dbde37 100644 --- a/types/catalog.go +++ b/types/catalog.go @@ -2,6 +2,8 @@ package types import ( "fmt" + "runtime/cgo" + "sync" "unsafe" internal "github.com/goccy/go-zetasql/internal/ccall/go-zetasql" @@ -27,7 +29,6 @@ type Catalog interface { SuggestFunction(mistypedPath []string) string SuggestTableValuedFunction(mistypedPath []string) string SuggestConstant(mistypedPath []string) string - getRaw() unsafe.Pointer } type EnumerableCatalog interface { @@ -509,11 +510,11 @@ func (c *SimpleCatalog) ConstantNames() []string { } func (c *SimpleCatalog) AddTable(table Table) { - internal.SimpleCatalog_AddTable(c.raw, table.getRaw()) + internal.SimpleCatalog_AddTable(c.raw, getRawTable(table)) } func (c *SimpleCatalog) AddTableWithName(name string, table Table) { - internal.SimpleCatalog_AddTableWithName(c.raw, helper.StringToPtr(name), table.getRaw()) + internal.SimpleCatalog_AddTableWithName(c.raw, helper.StringToPtr(name), getRawTable(table)) } func (c *SimpleCatalog) AddModel(model Model) { @@ -543,11 +544,11 @@ func (c *SimpleCatalog) AddTypeIfNotPresent(name string, typ Type) bool { } func (c *SimpleCatalog) AddCatalog(catalog Catalog) { - internal.SimpleCatalog_AddCatalog(c.raw, catalog.getRaw()) + internal.SimpleCatalog_AddCatalog(c.raw, getRawCatalog(catalog)) } func (c *SimpleCatalog) AddCatalogWithName(name string, catalog Catalog) { - internal.SimpleCatalog_AddCatalogWithName(c.raw, helper.StringToPtr(name), catalog.getRaw()) + internal.SimpleCatalog_AddCatalogWithName(c.raw, helper.StringToPtr(name), getRawCatalog(catalog)) } func (c *SimpleCatalog) AddFunction(fn *Function) { @@ -594,6 +595,128 @@ func (c *SimpleCatalog) AddZetaSQLBuiltinFunctions(opt *BuiltinFunctionOptions) internal.SimpleCatalog_AddZetaSQLFunctions(c.raw, opt.raw) } +var ( + catalogMap = map[Catalog]unsafe.Pointer{} + catalogMapMu sync.Mutex +) + func getRawCatalog(c Catalog) unsafe.Pointer { - return c.getRaw() + switch cat := c.(type) { + case *SimpleCatalog: + return cat.getRaw() + } + catalogMapMu.Lock() + defer catalogMapMu.Unlock() + + ptr, exists := catalogMap[c] + if exists { + return ptr + } + + goCatalog := &internal.GoCatalog{ + FullName: func() string { + return c.FullName() + }, + FindTable: func(path []string) (unsafe.Pointer, error) { + table, err := c.FindTable(path) + if err != nil { + return nil, err + } + return getRawTable(table), nil + }, + FindModel: func(path []string) (unsafe.Pointer, error) { + model, err := c.FindModel(path) + if err != nil { + return nil, err + } + return model.getRaw(), nil + }, + FindConnection: func(path []string) (unsafe.Pointer, error) { + conn, err := c.FindConnection(path) + if err != nil { + return nil, err + } + return conn.getRaw(), nil + }, + FindFunction: func(path []string) (unsafe.Pointer, error) { + fn, err := c.FindFunction(path) + if err != nil { + return nil, err + } + if fn == nil { + return nil, nil + } + return fn.raw, nil + }, + FindTableValuedFunction: func(path []string) (unsafe.Pointer, error) { + fn, err := c.FindTableValuedFunction(path) + if err != nil { + return nil, err + } + return fn.getRaw(), nil + }, + FindProcedure: func(path []string) (unsafe.Pointer, error) { + proc, err := c.FindProcedure(path) + if err != nil { + return nil, err + } + if proc == nil { + return nil, nil + } + return proc.raw, nil + }, + FindType: func(path []string) (unsafe.Pointer, error) { + t, err := c.FindType(path) + if err != nil { + return nil, err + } + return t.getRaw(), nil + }, + FindConstant: func(path []string) (unsafe.Pointer, error) { + constant, err := c.FindConstant(path) + if err != nil { + return nil, err + } + return constant.getRaw(), nil + }, + FindConversion: func(from, to unsafe.Pointer) (unsafe.Pointer, error) { + conv, err := c.FindConversion(newType(from), newType(to)) + if err != nil { + return nil, err + } + if conv == nil { + return nil, nil + } + // TODO + return nil, nil + }, + ExtendedTypeSuperTypes: func(typ unsafe.Pointer) (unsafe.Pointer, error) { + if _, err := c.ExtendedTypeSuperTypes(newType(typ)); err != nil { + return nil, err + } + // TODO + return nil, nil + }, + SuggestTable: func(mistypedPath []string) string { + return c.SuggestTable(mistypedPath) + }, + SuggestModel: func(mistypedPath []string) string { + return c.SuggestModel(mistypedPath) + }, + SuggestFunction: func(mistypedPath []string) string { + return c.SuggestFunction(mistypedPath) + }, + SuggestTableValuedFunction: func(mistypedPath []string) string { + return c.SuggestTableValuedFunction(mistypedPath) + }, + SuggestConstant: func(mistypedPath []string) string { + return c.SuggestConstant(mistypedPath) + }, + } + + h := cgo.NewHandle(goCatalog) + var ret unsafe.Pointer + internal.GoCatalog_new(unsafe.Pointer(&h), &ret) + catalogMap[c] = ret + return ret } diff --git a/types/table.go b/types/table.go index 18d8a658..dbd992be 100644 --- a/types/table.go +++ b/types/table.go @@ -2,6 +2,8 @@ package types import ( "reflect" + "runtime/cgo" + "sync" "unsafe" internal "github.com/goccy/go-zetasql/internal/ccall/go-zetasql" @@ -34,7 +36,6 @@ type Table interface { AnonymizationInfo() *AnonymizationInfo SupportsAnonymization() bool TableTypeName(mode ProductMode) string - getRaw() unsafe.Pointer } type BaseTable struct { @@ -237,6 +238,80 @@ func newTable(v unsafe.Pointer) Table { return &SimpleTable{BaseTable: &BaseTable{raw: v}} } +var ( + tableMap = map[Table]unsafe.Pointer{} + tableMapMu sync.Mutex +) + func getRawTable(v Table) unsafe.Pointer { - return v.getRaw() + if v == nil { + return nil + } + switch t := v.(type) { + case *SimpleTable: + return t.getRaw() + } + + tableMapMu.Lock() + defer tableMapMu.Unlock() + + ptr, exists := tableMap[v] + if exists { + return ptr + } + + goTable := &internal.GoTable{ + Name: func() string { + return v.Name() + }, + FullName: func() string { + return v.FullName() + }, + NumColumns: func() int { + return v.NumColumns() + }, + Column: func(idx int) unsafe.Pointer { + c := v.Column(idx) + return c.getRaw() + }, + PrimaryKey: func() []int { + return v.PrimaryKey() + }, + FindColumnByName: func(name string) unsafe.Pointer { + c := v.FindColumnByName(name) + return c.getRaw() + }, + IsValueTable: func() bool { + return v.IsValueTable() + }, + SerializationID: func() int64 { + return v.SerializationID() + }, + CreateEvaluatorTableIterator: func(columnIdxs []int) (unsafe.Pointer, error) { + iter, err := v.CreateEvaluatorTableIterator(columnIdxs) + if err != nil { + return nil, err + } + return iter.raw, nil + }, + AnonymizationInfo: func() unsafe.Pointer { + ret := v.AnonymizationInfo() + if ret == nil { + return nil + } + return ret.raw + }, + SupportsAnonymization: func() bool { + return v.SupportsAnonymization() + }, + TableTypeName: func(mode int) string { + return v.TableTypeName(ProductMode(mode)) + }, + } + + h := cgo.NewHandle(goTable) + var ret unsafe.Pointer + internal.GoTable_new(unsafe.Pointer(&h), &ret) + tableMap[v] = ret + return ret }