forked from marcboeker/go-duckdb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
replacement_scan.go
64 lines (56 loc) · 1.88 KB
/
replacement_scan.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package duckdb
/*
#include <duckdb.h>
void replacement_scan_cb(duckdb_replacement_scan_info info, const char *table_name, void *data);
typedef const char cchar_t;
void replacement_scan_destroy_data(void *);
*/
import "C"
import (
"runtime/cgo"
"unsafe"
)
type ReplacementScanCallback func(tableName string) (string, []any, error)
func RegisterReplacementScan(connector *Connector, cb ReplacementScanCallback) {
handle := cgo.NewHandle(cb)
C.duckdb_add_replacement_scan(connector.db, C.duckdb_replacement_callback_t(C.replacement_scan_cb), unsafe.Pointer(&handle), C.duckdb_delete_callback_t(C.replacement_scan_destroy_data))
}
//export replacement_scan_destroy_data
func replacement_scan_destroy_data(data unsafe.Pointer) {
h := *(*cgo.Handle)(data)
h.Delete()
}
//export replacement_scan_cb
func replacement_scan_cb(info C.duckdb_replacement_scan_info, table_name *C.cchar_t, data *C.void) {
h := *(*cgo.Handle)(unsafe.Pointer(data))
scanner := h.Value().(ReplacementScanCallback)
tFunc, params, err := scanner(C.GoString(table_name))
if err != nil {
errStr := C.CString(err.Error())
defer C.duckdb_free(unsafe.Pointer(errStr))
C.duckdb_replacement_scan_set_error(info, errStr)
return
}
fNameStr := C.CString(tFunc)
C.duckdb_replacement_scan_set_function_name(info, fNameStr)
defer C.duckdb_free(unsafe.Pointer(fNameStr))
for _, v := range params {
switch x := v.(type) {
case string:
str := C.CString(x)
val := C.duckdb_create_varchar(str)
C.duckdb_replacement_scan_add_parameter(info, val)
C.duckdb_free(unsafe.Pointer(str))
C.duckdb_destroy_value(&val)
case int64:
val := C.duckdb_create_int64(C.int64_t(x))
C.duckdb_replacement_scan_add_parameter(info, val)
C.duckdb_destroy_value(&val)
default:
errStr := C.CString("invalid type")
C.duckdb_replacement_scan_set_error(info, errStr)
C.duckdb_free(unsafe.Pointer(errStr))
return
}
}
}