go/adbc/pkg/panicdummy/driver.go (738 lines of code) (raw):

// Code generated by _tmpl/driver.go.tmpl. DO NOT EDIT. // Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you 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 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. //go:build driverlib package main // ADBC_EXPORTING is required on Windows, or else the symbols // won't be accessible to the driver manager // #cgo CFLAGS: -DADBC_EXPORTING // #cgo CXXFLAGS: -std=c++11 -DADBC_EXPORTING // #include "../../drivermgr/adbc.h" // #include "utils.h" // #include <stdint.h> // #include <string.h> // // typedef const char cchar_t; // typedef const uint8_t cuint8_t; // // void releasePartitions(struct AdbcPartitions* partitions); // import "C" import ( "context" "errors" "fmt" "os" "runtime" "runtime/cgo" "sync/atomic" "unsafe" "github.com/apache/arrow-adbc/go/adbc" "github.com/apache/arrow-adbc/go/adbc/driver/panicdummy" "github.com/apache/arrow/go/v13/arrow/array" "github.com/apache/arrow/go/v13/arrow/cdata" "github.com/apache/arrow/go/v13/arrow/memory/mallocator" ) // Must use malloc() to respect CGO rules var drv = panicdummy.Driver{Alloc: mallocator.NewMallocator()} // Flag set if any method panic()ed - afterwards all calls to driver will fail // since internal state of driver is unknown // (Can't use atomic.Bool since that's Go 1.19) var globalPoison int32 = 0 const errPrefix = "[PanicDummy] " func setErr(err *C.struct_AdbcError, format string, vals ...interface{}) { if err == nil { return } if err.release != nil { C.PanicDummyerrRelease(err) } msg := errPrefix + fmt.Sprintf(format, vals...) err.message = C.CString(msg) err.release = (*[0]byte)(C.PanicDummy_release_error) } func errToAdbcErr(adbcerr *C.struct_AdbcError, err error) adbc.Status { if adbcerr == nil || err == nil { return adbc.StatusOK } var adbcError adbc.Error if errors.As(err, &adbcError) { setErr(adbcerr, adbcError.Msg) return adbcError.Code } setErr(adbcerr, err.Error()) return adbc.StatusUnknown } // We panicked; make all API functions error and dump stack traces func poison(err *C.struct_AdbcError, fname string, e interface{}) C.AdbcStatusCode { if atomic.SwapInt32(&globalPoison, 1) == 0 { // Only print stack traces on the first occurrence buf := make([]byte, 1<<20) length := runtime.Stack(buf, true) fmt.Fprintf(os.Stderr, "PanicDummy driver panicked, stack traces:\n%s", buf[:length]) } setErr(err, "%s: Go panic in PanicDummy driver (see stderr): %#v", fname, e) return C.ADBC_STATUS_INTERNAL } // Allocate a new cgo.Handle and store its address in a heap-allocated // uintptr_t. Experimentally, this was found to be necessary, else // something (the Go runtime?) would corrupt (garbage-collect?) the // handle. func createHandle(hndl cgo.Handle) unsafe.Pointer { // uintptr_t* hptr = malloc(sizeof(uintptr_t)); hptr := (*C.uintptr_t)(C.malloc(C.sizeof_uintptr_t)) // *hptr = (uintptr)hndl; *hptr = C.uintptr_t(uintptr(hndl)) return unsafe.Pointer(hptr) } func getFromHandle[T any](ptr unsafe.Pointer) *T { // uintptr_t* hptr = (uintptr_t*)ptr; hptr := (*C.uintptr_t)(ptr) return cgo.Handle((uintptr)(*hptr)).Value().(*T) } func checkDBAlloc(db *C.struct_AdbcDatabase, err *C.struct_AdbcError, fname string) bool { if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "%s: Go panicked, driver is in unknown state", fname) return false } if db == nil { setErr(err, "%s: database not allocated", fname) return false } if db.private_data == nil { setErr(err, "%s: database not allocated", fname) return false } return true } func checkDBInit(db *C.struct_AdbcDatabase, err *C.struct_AdbcError, fname string) *cDatabase { if !checkDBAlloc(db, err, fname) { return nil } cdb := getFromHandle[cDatabase](db.private_data) if cdb.db == nil { setErr(err, "%s: database not initialized", fname) return nil } return cdb } type cDatabase struct { opts map[string]string db adbc.Database } //export PanicDummyDatabaseNew func PanicDummyDatabaseNew(db *C.struct_AdbcDatabase, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcDatabaseNew", e) } }() if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "AdbcDatabaseNew: Go panicked, driver is in unknown state") return C.ADBC_STATUS_INTERNAL } if db.private_data != nil { setErr(err, "AdbcDatabaseNew: database already allocated") return C.ADBC_STATUS_INVALID_STATE } dbobj := &cDatabase{opts: make(map[string]string)} hndl := cgo.NewHandle(dbobj) db.private_data = createHandle(hndl) return C.ADBC_STATUS_OK } //export PanicDummyDatabaseSetOption func PanicDummyDatabaseSetOption(db *C.struct_AdbcDatabase, key, value *C.cchar_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcDatabaseSetOption", e) } }() if !checkDBAlloc(db, err, "AdbcDatabaseSetOption") { return C.ADBC_STATUS_INVALID_STATE } cdb := getFromHandle[cDatabase](db.private_data) k, v := C.GoString(key), C.GoString(value) cdb.opts[k] = v return C.ADBC_STATUS_OK } //export PanicDummyDatabaseInit func PanicDummyDatabaseInit(db *C.struct_AdbcDatabase, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcDatabaseInit", e) } }() if !checkDBAlloc(db, err, "AdbcDatabaseInit") { return C.ADBC_STATUS_INVALID_STATE } cdb := getFromHandle[cDatabase](db.private_data) if cdb.db != nil { setErr(err, "AdbcDatabaseInit: database already initialized") return C.ADBC_STATUS_INVALID_STATE } adb, aerr := drv.NewDatabase(cdb.opts) if aerr != nil { return C.AdbcStatusCode(errToAdbcErr(err, aerr)) } cdb.db = adb return C.ADBC_STATUS_OK } //export PanicDummyDatabaseRelease func PanicDummyDatabaseRelease(db *C.struct_AdbcDatabase, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcDatabaseInit", e) } }() if !checkDBAlloc(db, err, "AdbcDatabaseRelease") { return C.ADBC_STATUS_INVALID_STATE } h := (*(*cgo.Handle)(db.private_data)) cdb := h.Value().(*cDatabase) cdb.db = nil cdb.opts = nil C.free(unsafe.Pointer(db.private_data)) db.private_data = nil h.Delete() // manually trigger GC for two reasons: // 1. ASAN expects the release callback to be called before // the process ends, but GC is not deterministic. So by manually // triggering the GC we ensure the release callback gets called. // 2. Creates deterministic GC behavior by all Release functions // triggering a garbage collection runtime.GC() return C.ADBC_STATUS_OK } type cConn struct { cnxn adbc.Connection initArgs map[string]string } func checkConnAlloc(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError, fname string) bool { if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "%s: Go panicked, driver is in unknown state", fname) return false } if cnxn == nil { setErr(err, "%s: connection not allocated", fname) return false } if cnxn.private_data == nil { setErr(err, "%s: connection not allocated", fname) return false } return true } func checkConnInit(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError, fname string) *cConn { if !checkConnAlloc(cnxn, err, fname) { return nil } conn := getFromHandle[cConn](cnxn.private_data) if conn.cnxn == nil { setErr(err, "%s: connection not initialized", fname) return nil } return conn } //export PanicDummyConnectionNew func PanicDummyConnectionNew(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionNew", e) } }() if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "AdbcConnectionNew: Go panicked, driver is in unknown state") return C.ADBC_STATUS_INTERNAL } if cnxn.private_data != nil { setErr(err, "AdbcConnectionNew: connection already allocated") return C.ADBC_STATUS_INVALID_STATE } hndl := cgo.NewHandle(&cConn{}) cnxn.private_data = createHandle(hndl) return C.ADBC_STATUS_OK } //export PanicDummyConnectionSetOption func PanicDummyConnectionSetOption(cnxn *C.struct_AdbcConnection, key, val *C.cchar_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionSetOption", e) } }() if !checkConnAlloc(cnxn, err, "AdbcConnectionSetOption") { return C.ADBC_STATUS_INVALID_STATE } conn := getFromHandle[cConn](cnxn.private_data) if conn.cnxn == nil { // not yet initialized k, v := C.GoString(key), C.GoString(val) if conn.initArgs == nil { conn.initArgs = map[string]string{} } conn.initArgs[k] = v return C.ADBC_STATUS_OK } opts, ok := conn.cnxn.(adbc.PostInitOptions) if !ok { setErr(err, "AdbcConnectionSetOption: not supported post-init") return C.ADBC_STATUS_NOT_IMPLEMENTED } rawCode := errToAdbcErr(err, opts.SetOption(C.GoString(key), C.GoString(val))) return C.AdbcStatusCode(rawCode) } //export PanicDummyConnectionInit func PanicDummyConnectionInit(cnxn *C.struct_AdbcConnection, db *C.struct_AdbcDatabase, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionInit", e) } }() if !checkConnAlloc(cnxn, err, "AdbcConnectionInit") { return C.ADBC_STATUS_INVALID_STATE } conn := getFromHandle[cConn](cnxn.private_data) if conn.cnxn != nil { setErr(err, "AdbcConnectionInit: connection already initialized") return C.ADBC_STATUS_INVALID_STATE } cdb := checkDBInit(db, err, "AdbcConnectionInit") if cdb == nil { return C.ADBC_STATUS_INVALID_STATE } c, e := cdb.db.Open(context.Background()) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } conn.cnxn = c if len(conn.initArgs) > 0 { // C allow SetOption before Init, Go doesn't allow options to Open so set them now opts, ok := conn.cnxn.(adbc.PostInitOptions) if !ok { setErr(err, "AdbcConnectionInit: options are not supported") return C.ADBC_STATUS_NOT_IMPLEMENTED } for k, v := range conn.initArgs { rawCode := errToAdbcErr(err, opts.SetOption(k, v)) if rawCode != adbc.StatusOK { return C.AdbcStatusCode(rawCode) } } conn.initArgs = nil } return C.ADBC_STATUS_OK } //export PanicDummyConnectionRelease func PanicDummyConnectionRelease(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionRelease", e) } }() if !checkConnAlloc(cnxn, err, "AdbcConnectionRelease") { return C.ADBC_STATUS_INVALID_STATE } h := (*(*cgo.Handle)(cnxn.private_data)) conn := h.Value().(*cConn) defer func() { conn.cnxn = nil C.free(unsafe.Pointer(cnxn.private_data)) cnxn.private_data = nil h.Delete() // manually trigger GC for two reasons: // 1. ASAN expects the release callback to be called before // the process ends, but GC is not deterministic. So by manually // triggering the GC we ensure the release callback gets called. // 2. Creates deterministic GC behavior by all Release functions // triggering a garbage collection runtime.GC() }() if conn.cnxn == nil { return C.ADBC_STATUS_OK } return C.AdbcStatusCode(errToAdbcErr(err, conn.cnxn.Close())) } func fromCArr[T, CType any](ptr *CType, sz int) []T { if ptr == nil || sz == 0 { return nil } return unsafe.Slice((*T)(unsafe.Pointer(ptr)), sz) } func toCdataStream(ptr *C.struct_ArrowArrayStream) *cdata.CArrowArrayStream { return (*cdata.CArrowArrayStream)(unsafe.Pointer(ptr)) } func toCdataSchema(ptr *C.struct_ArrowSchema) *cdata.CArrowSchema { return (*cdata.CArrowSchema)(unsafe.Pointer(ptr)) } func toCdataArray(ptr *C.struct_ArrowArray) *cdata.CArrowArray { return (*cdata.CArrowArray)(unsafe.Pointer(ptr)) } //export PanicDummyConnectionGetInfo func PanicDummyConnectionGetInfo(cnxn *C.struct_AdbcConnection, codes *C.uint32_t, len C.size_t, out *C.struct_ArrowArrayStream, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionGetInfo", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionGetInfo") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } infoCodes := fromCArr[adbc.InfoCode](codes, int(len)) rdr, e := conn.cnxn.GetInfo(context.Background(), infoCodes) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } defer rdr.Release() cdata.ExportRecordReader(rdr, toCdataStream(out)) return C.ADBC_STATUS_OK } func toStrPtr(in *C.cchar_t) *string { if in == nil { return nil } out := C.GoString((*C.char)(in)) return &out } func toStrSlice(in **C.cchar_t) []string { if in == nil { return nil } sz := unsafe.Sizeof(*in) out := make([]string, 0, 1) for *in != nil { out = append(out, C.GoString(*in)) in = (**C.cchar_t)(unsafe.Add(unsafe.Pointer(in), sz)) } return out } //export PanicDummyConnectionGetObjects func PanicDummyConnectionGetObjects(cnxn *C.struct_AdbcConnection, depth C.int, catalog, dbSchema, tableName *C.cchar_t, tableType **C.cchar_t, columnName *C.cchar_t, out *C.struct_ArrowArrayStream, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionGetObjects", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionGetObjects") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } rdr, e := conn.cnxn.GetObjects(context.Background(), adbc.ObjectDepth(depth), toStrPtr(catalog), toStrPtr(dbSchema), toStrPtr(tableName), toStrPtr(columnName), toStrSlice(tableType)) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } defer rdr.Release() cdata.ExportRecordReader(rdr, toCdataStream(out)) return C.ADBC_STATUS_OK } //export PanicDummyConnectionGetTableSchema func PanicDummyConnectionGetTableSchema(cnxn *C.struct_AdbcConnection, catalog, dbSchema, tableName *C.cchar_t, schema *C.struct_ArrowSchema, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionGetTableSchema", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionGetTableSchema") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } sc, e := conn.cnxn.GetTableSchema(context.Background(), toStrPtr(catalog), toStrPtr(dbSchema), C.GoString(tableName)) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } cdata.ExportArrowSchema(sc, toCdataSchema(schema)) return C.ADBC_STATUS_OK } //export PanicDummyConnectionGetTableTypes func PanicDummyConnectionGetTableTypes(cnxn *C.struct_AdbcConnection, out *C.struct_ArrowArrayStream, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionGetTableTypes", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionGetTableTypes") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } rdr, e := conn.cnxn.GetTableTypes(context.Background()) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } defer rdr.Release() cdata.ExportRecordReader(rdr, toCdataStream(out)) return C.ADBC_STATUS_OK } //export PanicDummyConnectionReadPartition func PanicDummyConnectionReadPartition(cnxn *C.struct_AdbcConnection, serialized *C.cuint8_t, serializedLen C.size_t, out *C.struct_ArrowArrayStream, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionReadPartition", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionReadPartition") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } rdr, e := conn.cnxn.ReadPartition(context.Background(), fromCArr[byte](serialized, int(serializedLen))) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } defer rdr.Release() cdata.ExportRecordReader(rdr, toCdataStream(out)) return C.ADBC_STATUS_OK } //export PanicDummyConnectionCommit func PanicDummyConnectionCommit(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionCommit", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionCommit") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, conn.cnxn.Commit(context.Background()))) } //export PanicDummyConnectionRollback func PanicDummyConnectionRollback(cnxn *C.struct_AdbcConnection, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcConnectionRollback", e) } }() conn := checkConnInit(cnxn, err, "AdbcConnectionRollback") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, conn.cnxn.Rollback(context.Background()))) } func checkStmtInit(stmt *C.struct_AdbcStatement, err *C.struct_AdbcError, fname string) adbc.Statement { if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "%s: Go panicked, driver is in unknown state", fname) return nil } if stmt == nil { setErr(err, "%s: statement not allocated", fname) return nil } if stmt.private_data == nil { setErr(err, "%s: statement not initialized", fname) return nil } return (*(*cgo.Handle)(stmt.private_data)).Value().(adbc.Statement) } //export PanicDummyStatementNew func PanicDummyStatementNew(cnxn *C.struct_AdbcConnection, stmt *C.struct_AdbcStatement, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementNew", e) } }() if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "AdbcStatementNew: Go panicked, driver is in unknown state") return C.ADBC_STATUS_INTERNAL } if stmt.private_data != nil { setErr(err, "AdbcStatementNew: statement already allocated") return C.ADBC_STATUS_INVALID_STATE } conn := checkConnInit(cnxn, err, "AdbcStatementNew") if conn == nil { return C.ADBC_STATUS_INVALID_STATE } st, e := conn.cnxn.NewStatement() if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } h := cgo.NewHandle(st) stmt.private_data = createHandle(h) return C.ADBC_STATUS_OK } //export PanicDummyStatementRelease func PanicDummyStatementRelease(stmt *C.struct_AdbcStatement, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementRelease", e) } }() if atomic.LoadInt32(&globalPoison) != 0 { setErr(err, "AdbcStatementRelease: Go panicked, driver is in unknown state") return C.ADBC_STATUS_INTERNAL } if stmt == nil { setErr(err, "AdbcStatementRelease: statement not allocated") return C.ADBC_STATUS_INVALID_STATE } if stmt.private_data == nil { setErr(err, "AdbcStatementRelease: statement not initialized") return C.ADBC_STATUS_INVALID_STATE } h := (*(*cgo.Handle)(stmt.private_data)) st := h.Value().(adbc.Statement) C.free(stmt.private_data) stmt.private_data = nil e := st.Close() h.Delete() // manually trigger GC for two reasons: // 1. ASAN expects the release callback to be called before // the process ends, but GC is not deterministic. So by manually // triggering the GC we ensure the release callback gets called. // 2. Creates deterministic GC behavior by all Release functions // triggering a garbage collection runtime.GC() return C.AdbcStatusCode(errToAdbcErr(err, e)) } //export PanicDummyStatementPrepare func PanicDummyStatementPrepare(stmt *C.struct_AdbcStatement, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementPrepare", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementPrepare") if st == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, st.Prepare(context.Background()))) } //export PanicDummyStatementExecuteQuery func PanicDummyStatementExecuteQuery(stmt *C.struct_AdbcStatement, out *C.struct_ArrowArrayStream, affected *C.int64_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementExecuteQuery", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementExecuteQuery") if st == nil { return C.ADBC_STATUS_INVALID_STATE } if out == nil { n, e := st.ExecuteUpdate(context.Background()) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } if affected != nil { *affected = C.int64_t(n) } } else { rdr, n, e := st.ExecuteQuery(context.Background()) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } if affected != nil { *affected = C.int64_t(n) } defer rdr.Release() cdata.ExportRecordReader(rdr, toCdataStream(out)) } return C.ADBC_STATUS_OK } //export PanicDummyStatementSetSqlQuery func PanicDummyStatementSetSqlQuery(stmt *C.struct_AdbcStatement, query *C.cchar_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementSetSqlQuery", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementSetSqlQuery") if st == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, st.SetSqlQuery(C.GoString(query)))) } //export PanicDummyStatementSetSubstraitPlan func PanicDummyStatementSetSubstraitPlan(stmt *C.struct_AdbcStatement, plan *C.cuint8_t, length C.size_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementSetSubstraitPlan", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementSetSubstraitPlan") if st == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, st.SetSubstraitPlan(fromCArr[byte](plan, int(length))))) } //export PanicDummyStatementBind func PanicDummyStatementBind(stmt *C.struct_AdbcStatement, values *C.struct_ArrowArray, schema *C.struct_ArrowSchema, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementBind", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementBind") if st == nil { return C.ADBC_STATUS_INVALID_STATE } rec, e := cdata.ImportCRecordBatch(toCdataArray(values), toCdataSchema(schema)) if e != nil { // if there was an error, we need to manually release the input cdata.ReleaseCArrowArray(toCdataArray(values)) return C.AdbcStatusCode(errToAdbcErr(err, e)) } defer rec.Release() return C.AdbcStatusCode(errToAdbcErr(err, st.Bind(context.Background(), rec))) } //export PanicDummyStatementBindStream func PanicDummyStatementBindStream(stmt *C.struct_AdbcStatement, stream *C.struct_ArrowArrayStream, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementBindStream", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementBindStream") if st == nil { return C.ADBC_STATUS_INVALID_STATE } rdr, e := cdata.ImportCRecordReader(toCdataStream(stream), nil) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } return C.AdbcStatusCode(errToAdbcErr(err, st.BindStream(context.Background(), rdr.(array.RecordReader)))) } //export PanicDummyStatementGetParameterSchema func PanicDummyStatementGetParameterSchema(stmt *C.struct_AdbcStatement, schema *C.struct_ArrowSchema, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementGetParameterSchema", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementGetParameterSchema") if st == nil { return C.ADBC_STATUS_INVALID_STATE } sc, e := st.GetParameterSchema() if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } cdata.ExportArrowSchema(sc, toCdataSchema(schema)) return C.ADBC_STATUS_OK } //export PanicDummyStatementSetOption func PanicDummyStatementSetOption(stmt *C.struct_AdbcStatement, key, value *C.cchar_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementSetOption", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementSetOption") if st == nil { return C.ADBC_STATUS_INVALID_STATE } return C.AdbcStatusCode(errToAdbcErr(err, st.SetOption(C.GoString(key), C.GoString(value)))) } //export releasePartitions func releasePartitions(partitions *C.struct_AdbcPartitions) { if partitions.private_data == nil { return } C.free(unsafe.Pointer(partitions.partitions)) C.free(unsafe.Pointer(partitions.partition_lengths)) C.free(partitions.private_data) partitions.partitions = nil partitions.partition_lengths = nil partitions.private_data = nil } //export PanicDummyStatementExecutePartitions func PanicDummyStatementExecutePartitions(stmt *C.struct_AdbcStatement, schema *C.struct_ArrowSchema, partitions *C.struct_AdbcPartitions, affected *C.int64_t, err *C.struct_AdbcError) (code C.AdbcStatusCode) { defer func() { if e := recover(); e != nil { code = poison(err, "AdbcStatementExecutePartitions", e) } }() st := checkStmtInit(stmt, err, "AdbcStatementExecutePartitions") if st == nil { return C.ADBC_STATUS_INVALID_STATE } sc, part, n, e := st.ExecutePartitions(context.Background()) if e != nil { return C.AdbcStatusCode(errToAdbcErr(err, e)) } if partitions == nil { setErr(err, "AdbcStatementExecutePartitions: partitions output struct is null") return C.ADBC_STATUS_INVALID_ARGUMENT } if affected != nil { *affected = C.int64_t(n) } if sc != nil && schema != nil { cdata.ExportArrowSchema(sc, toCdataSchema(schema)) } partitions.num_partitions = C.size_t(part.NumPartitions) partitions.partitions = (**C.cuint8_t)(C.malloc(C.size_t(unsafe.Sizeof((*C.uint8_t)(nil)) * uintptr(part.NumPartitions)))) partitions.partition_lengths = (*C.size_t)(C.malloc(C.size_t(unsafe.Sizeof(C.size_t(0)) * uintptr(part.NumPartitions)))) // Copy into C-allocated memory to avoid violating CGO rules totalLen := 0 for _, p := range part.PartitionIDs { totalLen += len(p) } partitions.private_data = C.malloc(C.size_t(totalLen)) dst := fromCArr[byte]((*byte)(partitions.private_data), totalLen) partIDs := fromCArr[*C.cuint8_t](partitions.partitions, int(partitions.num_partitions)) partLens := fromCArr[C.size_t](partitions.partition_lengths, int(partitions.num_partitions)) for i, p := range part.PartitionIDs { partIDs[i] = (*C.cuint8_t)(&dst[0]) copy(dst, p) dst = dst[len(p):] partLens[i] = C.size_t(len(p)) } partitions.release = (*[0]byte)(C.releasePartitions) return C.ADBC_STATUS_OK } //export PanicDummyDriverInit func PanicDummyDriverInit(version C.int, rawDriver *C.void, err *C.struct_AdbcError) C.AdbcStatusCode { if version != C.ADBC_VERSION_1_0_0 { setErr(err, "Only version %d supported, got %d", int(C.ADBC_VERSION_1_0_0), int(version)) return C.ADBC_STATUS_NOT_IMPLEMENTED } driver := (*C.struct_AdbcDriver)(unsafe.Pointer(rawDriver)) C.memset(unsafe.Pointer(driver), 0, C.sizeof_struct_AdbcDriver) driver.DatabaseInit = (*[0]byte)(C.PanicDummyDatabaseInit) driver.DatabaseNew = (*[0]byte)(C.PanicDummyDatabaseNew) driver.DatabaseRelease = (*[0]byte)(C.PanicDummyDatabaseRelease) driver.DatabaseSetOption = (*[0]byte)(C.PanicDummyDatabaseSetOption) driver.ConnectionNew = (*[0]byte)(C.PanicDummyConnectionNew) driver.ConnectionInit = (*[0]byte)(C.PanicDummyConnectionInit) driver.ConnectionRelease = (*[0]byte)(C.PanicDummyConnectionRelease) driver.ConnectionSetOption = (*[0]byte)(C.PanicDummyConnectionSetOption) driver.ConnectionGetInfo = (*[0]byte)(C.PanicDummyConnectionGetInfo) driver.ConnectionGetObjects = (*[0]byte)(C.PanicDummyConnectionGetObjects) driver.ConnectionGetTableSchema = (*[0]byte)(C.PanicDummyConnectionGetTableSchema) driver.ConnectionGetTableTypes = (*[0]byte)(C.PanicDummyConnectionGetTableTypes) driver.ConnectionReadPartition = (*[0]byte)(C.PanicDummyConnectionReadPartition) driver.ConnectionCommit = (*[0]byte)(C.PanicDummyConnectionCommit) driver.ConnectionRollback = (*[0]byte)(C.PanicDummyConnectionRollback) driver.StatementNew = (*[0]byte)(C.PanicDummyStatementNew) driver.StatementRelease = (*[0]byte)(C.PanicDummyStatementRelease) driver.StatementSetOption = (*[0]byte)(C.PanicDummyStatementSetOption) driver.StatementSetSqlQuery = (*[0]byte)(C.PanicDummyStatementSetSqlQuery) driver.StatementSetSubstraitPlan = (*[0]byte)(C.PanicDummyStatementSetSubstraitPlan) driver.StatementBind = (*[0]byte)(C.PanicDummyStatementBind) driver.StatementBindStream = (*[0]byte)(C.PanicDummyStatementBindStream) driver.StatementExecuteQuery = (*[0]byte)(C.PanicDummyStatementExecuteQuery) driver.StatementExecutePartitions = (*[0]byte)(C.PanicDummyStatementExecutePartitions) driver.StatementGetParameterSchema = (*[0]byte)(C.PanicDummyStatementGetParameterSchema) driver.StatementPrepare = (*[0]byte)(C.PanicDummyStatementPrepare) return C.ADBC_STATUS_OK } func main() {}