-
Notifications
You must be signed in to change notification settings - Fork 18
/
tarantool_sql.go
135 lines (127 loc) · 3 KB
/
tarantool_sql.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package Tt
import (
"log"
"time"
"github.com/kokizzu/gotro/A"
"github.com/kokizzu/gotro/L"
"github.com/kokizzu/gotro/X"
"github.com/tarantool/go-tarantool/v2"
)
/*
function T(sql_statement)
start_time = os.clock()
res = box.execute(sql_statement)
end_time = os.clock()
return box.tuple.new(res, 'Query done in ' .. string.format("%.2f",(end_time - start_time)*1000) .. ' ms')
end
*/
func (a *Adapter) ExecSql(query string, parameters ...MSX) map[any]any {
// https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_sql/#box-sql-box-execute
params := A.X{query}
for _, v := range parameters {
params = append(params, v)
}
//L.Describe(params)
res, err := a.Connection.Do(tarantool.NewCallRequest("box.execute").Args(params)).Get()
if L.IsError(err, `ExecSql box.execute failed: `+query) {
log.Println(`ERROR ExecSql !!! ` + err.Error())
//L.DescribeSql(query, parameters)
L.Describe(parameters)
//tracer.PanicOnDev(err)
return map[any]any{`error`: err.Error()}
}
if len(res) > 0 {
// go-tarantool/v2 use this:
if tup, ok := res[0].(map[any]any); ok {
// tup have metadata and rows for query
return tup
}
if tup, ok := res[0].([][]any); ok {
if tup[0][0] != nil {
kv, ok := tup[0][0].(map[any]any)
// row_count for UPDATE
// metadata, rows for SELECT
if ok {
return kv
}
}
}
}
// possible error
if len(res) > 1 {
if tup, ok := res[1].([][]any); ok {
if tup[1][0] != nil {
errStr := X.ToS(tup[1][0])
log.Println(`ERROR ExecSql syntax: ` + errStr)
//L.DescribeSql(query, parameters)
L.Describe(query)
L.Describe(parameters)
//tracer.PanicOnDev(errors.New(errStr))
return map[any]any{`error`: tup[1][0]}
}
}
// go-tarantool v2 use this kind of error
if boxErr, ok := res[1].(*tarantool.BoxError); ok && boxErr != nil {
L.Describe(query)
L.Print(boxErr)
return map[any]any{`error`: boxErr.Error()}
}
}
return map[any]any{}
}
func (a *Adapter) QuerySql(query string, callback func(row []any), parameters ...MSX) []any {
if DebugPerf {
defer L.TimeTrack(time.Now(), query)
}
kv := a.ExecSql(query, parameters...)
rows, ok := kv[`rows`].([]any)
if ok {
for _, v := range rows {
callback(v.([]any))
}
return rows
}
return nil
}
var DebugPerf = false
type QueryMeta struct {
Columns []tarantool.ColumnMetaData
SqlInfo tarantool.SQLInfo
Err string
Code uint32
}
func QueryMetaFrom(res tarantool.Response, err error) QueryMeta {
if res == nil {
if err != nil {
return QueryMeta{
Err: err.Error(),
}
}
return QueryMeta{}
}
exRes, ok := res.(*tarantool.ExecuteResponse)
if !ok {
if err != nil {
return QueryMeta{
Err: err.Error(),
}
}
return QueryMeta{
Err: `not ExecuteResponse`,
}
}
var errStr string
if err != nil {
errStr = err.Error()
}
columns, _ := exRes.MetaData()
sqlInfo, err := exRes.SQLInfo()
if err != nil && errStr == `` {
errStr = err.Error()
}
return QueryMeta{
Columns: columns,
SqlInfo: sqlInfo,
Err: errStr,
}
}