@@ -28,6 +28,8 @@ type DuckDB struct {
28
28
chunk int
29
29
cacheDuration int
30
30
cache cache
31
+ docker bool
32
+ image string
31
33
}
32
34
33
35
type Opts struct {
@@ -36,9 +38,14 @@ type Opts struct {
36
38
Chunk int
37
39
Exe string
38
40
CacheDuration int
41
+ Docker bool
42
+ Image string
39
43
}
40
44
41
45
const newline = "\n "
46
+ const duckdbImage = "datacatering/duckdb:v1.0.0"
47
+
48
+ var tempDir = getTempDir ()
42
49
43
50
// NewInMemoryDB creates a new in-memory DuckDB
44
51
func NewInMemoryDB (opts ... Opts ) * DuckDB {
@@ -68,10 +75,15 @@ func NewDuckDB(name string, opts ...Opts) *DuckDB {
68
75
if opt .CacheDuration > 0 {
69
76
db .cacheDuration = opt .CacheDuration
70
77
}
78
+ db .image = duckdbImage
79
+ if opt .Image != "" {
80
+ db .image = opt .Image
81
+ }
82
+ db .docker = opt .Docker
71
83
}
72
84
73
85
// Find the executable if it is not configured
74
- if db .exe == "" {
86
+ if db .exe == "" && ! db . docker {
75
87
db .exe = which .Which ("duckdb" )
76
88
if db .exe == "" {
77
89
db .exe = "/usr/local/bin/duckdb"
@@ -83,33 +95,7 @@ func NewDuckDB(name string, opts ...Opts) *DuckDB {
83
95
84
96
// RunCommands runs a series of of sql commands against duckdb
85
97
func (d * DuckDB ) RunCommands (commands []string ) (string , error ) {
86
- var stdout bytes.Buffer
87
- var stderr bytes.Buffer
88
-
89
- var b bytes.Buffer
90
- b .Write ([]byte (fmt .Sprintf (".mode %s %s" , d .mode , newline )))
91
- for _ , c := range commands {
92
- cmd := fmt .Sprintf ("%s %s" , c , newline )
93
- b .Write ([]byte (cmd ))
94
- }
95
-
96
- cmd := exec .Command (d .exe , d .Name )
97
- cmd .Stdin = & b
98
- cmd .Stdout = & stdout
99
- cmd .Stderr = & stderr
100
-
101
- err := cmd .Run ()
102
- if err != nil {
103
- message := err .Error () + stderr .String ()
104
- logger .Error ("error running command" , "cmd" , b .String (), "message" , message , "error" , err )
105
- return "" , errors .New (message )
106
- }
107
- if stderr .String () != "" {
108
- logger .Error ("error running command" , "cmd" , b .String (), "error" , stderr .String ())
109
- return "" , errors .New (stderr .String ())
110
- }
111
-
112
- return stdout .String (), nil
98
+ return d .runCommands (commands )
113
99
}
114
100
115
101
// Query runs a query against the database. For Databases that are NOT in-memory.
@@ -242,6 +228,42 @@ func resultsToFrame(name string, res string, f *sdk.Frame, frames []*sdk.Frame)
242
228
return nil
243
229
}
244
230
231
+ func (d * DuckDB ) runCommands (commands []string ) (string , error ) {
232
+ var stdout bytes.Buffer
233
+ var stderr bytes.Buffer
234
+
235
+ var b bytes.Buffer
236
+ b .Write ([]byte (fmt .Sprintf (".mode %s %s" , d .mode , newline )))
237
+ for _ , c := range commands {
238
+ cmd := fmt .Sprintf ("%s %s" , c , newline )
239
+ b .Write ([]byte (cmd ))
240
+ }
241
+
242
+ var cmd * exec.Cmd
243
+ if d .docker {
244
+ volume := fmt .Sprintf ("%s:%s" , tempDir , tempDir )
245
+ logger .Debug ("running command in docker" , "volume" , volume , "image" , duckdbImage )
246
+ cmd = exec .Command ("docker" , "run" , "-i" , "-v" , volume , duckdbImage )
247
+ } else {
248
+ cmd = exec .Command (d .exe , d .Name )
249
+ }
250
+ cmd .Stdin = & b
251
+ cmd .Stdout = & stdout
252
+ cmd .Stderr = & stderr
253
+
254
+ err := cmd .Run ()
255
+ if err != nil {
256
+ message := err .Error () + stderr .String ()
257
+ logger .Error ("error running command" , "cmd" , b .String (), "message" , message , "error" , err )
258
+ return "" , errors .New (message )
259
+ }
260
+ if stderr .String () != "" {
261
+ logger .Error ("error running command" , "cmd" , b .String (), "error" , stderr .String ())
262
+ return "" , errors .New (stderr .String ())
263
+ }
264
+ return stdout .String (), nil
265
+ }
266
+
245
267
// TODO
246
268
247
269
// func applyLabels(resultsFrame sdk.Frame, sourceFrames []*sdk.Frame) {
@@ -263,4 +285,12 @@ func resultsToFrame(name string, res string, f *sdk.Frame, frames []*sdk.Frame)
263
285
// }
264
286
// }
265
287
// return nil
266
- //
288
+ // }
289
+
290
+ func getTempDir () string {
291
+ temp := os .Getenv ("TMPDIR" )
292
+ if temp == "" {
293
+ temp = "/tmp"
294
+ }
295
+ return temp
296
+ }
0 commit comments