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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
Copyright (C) BABEC. All rights reserved.
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
// ResultSet iterator query result
type ResultSet interface {
// NextRow get next row,
// sql: column name is EasyCodec key, value is EasyCodec string val. as: val := ec.getString("columnName")
// kv iterator: key/value is EasyCodec key for "key"/"value", value type is []byte. as: k, _ := ec.GetString("key") v, _ := ec.GetBytes("value")
NextRow() (*EasyCodec, ResultCode)
// HasNext return does the next line exist
HasNext() bool
// close
Close() (bool, ResultCode)
}
type ResultSetKV interface {
ResultSet
// Next return key,field,value,code
Next() (string, string, []byte, ResultCode)
}
type SqlSimContext interface {
SimContextCommon
// sql method
// ExecuteQueryOne
ExecuteQueryOne(sql string) (*EasyCodec, ResultCode)
ExecuteQuery(sql string) (ResultSet, ResultCode)
// #### ExecuteUpdateSql execute update/insert/delete sql
// ##### It is best to update with primary key
//
// as:
//
// - update table set name = 'Tom' where uniqueKey='xxx'
// - delete from table where uniqueKey='xxx'
// - insert into table(id, xxx,xxx) values(xxx,xxx,xxx)
//
// ### not allow:
// - random methods: NOW() RAND() and so on
// return: 1 Number of rows affected;2 result code
ExecuteUpdate(sql string) (int32, ResultCode)
// ExecuteDDLSql execute DDL sql, for init_contract or upgrade method. allow table create/alter/drop/truncate
//
// ## You must have a primary key to create a table
// ### allow:
// - CREATE TABLE tableName
// - ALTER TABLE tableName
// - DROP TABLE tableName
// - TRUNCATE TABLE tableName
//
// ### not allow:
// - CREATE DATABASE dbName
// - CREATE TABLE dbName.tableName
// - ALTER TABLE dbName.tableName
// - DROP DATABASE dbName
// - DROP TABLE dbName.tableName
// - TRUNCATE TABLE dbName.tableName
// not allow:
// - random methods: NOW() RAND() and so on
//
ExecuteDdl(sql string) (int32, ResultCode)
}
type SqlSimContextImpl struct {
SimContextCommonImpl
}
func NewSqlSimContext() SqlSimContext {
return &SqlSimContextImpl{}
}
// sql
func (s *SqlSimContextImpl) ExecuteQueryOne(sql string) (*EasyCodec, ResultCode) {
ec := NewEasyCodec()
ec.AddString("sql", sql)
bytes, code := GetBytesFromChain(ec, ContractMethodExecuteQueryOneLen, ContractMethodExecuteQueryOne)
if code == SUCCESS {
return NewEasyCodecWithBytes(bytes), code
}
return NewEasyCodec(), ERROR
}
func (s *SqlSimContextImpl) ExecuteQuery(sql string) (ResultSet, ResultCode) {
ec := NewEasyCodec()
ec.AddString("sql", sql)
index, code := GetInt32FromChain(ec, ContractMethodExecuteQuery)
return NewResultSet(s, index), code
}
func (s *SqlSimContextImpl) ExecuteUpdate(sql string) (int32, ResultCode) {
ec := NewEasyCodec()
ec.AddString("sql", sql)
return GetInt32FromChain(ec, ContractMethodExecuteUpdate)
}
func (s *SqlSimContextImpl) ExecuteDdl(sql string) (int32, ResultCode) {
ec := NewEasyCodec()
ec.AddString("sql", sql)
return GetInt32FromChain(ec, ContractMethodExecuteDdl)
}
func (s *SqlSimContextImpl) IteratorNextRow(rsIndex int32) ([]byte, ResultCode) {
ec := NewEasyCodec()
ec.AddInt32("rs_index", rsIndex)
return GetBytesFromChain(ec, ContractMethodRSNextLen, ContractMethodRSNext)
}
func (s *SqlSimContextImpl) IteratorHasNext(rsIndex int32) (int32, ResultCode) {
ec := NewEasyCodec()
ec.AddInt32("rs_index", rsIndex)
return GetInt32FromChain(ec, ContractMethodRSHasNext)
}
func (s *SqlSimContextImpl) IteratorClose(rsIndex int32) (int32, ResultCode) {
ec := NewEasyCodec()
ec.AddInt32("rs_index", rsIndex)
return GetInt32FromChain(ec, ContractMethodRSClose)
}
type ResultSetImpl struct {
sqlCtx *SqlSimContextImpl
index int32 // 链的rs句柄的index
}
func NewResultSet(sqlCtx *SqlSimContextImpl, index int32) ResultSet {
return &ResultSetImpl{sqlCtx, index}
}
func (r *ResultSetImpl) NextRow() (*EasyCodec, ResultCode) {
bytes, code := r.sqlCtx.IteratorNextRow(r.index)
if code != SUCCESS {
return NewEasyCodec(), ERROR
}
return NewEasyCodecWithBytes(bytes), SUCCESS
}
func (r *ResultSetImpl) HasNext() bool {
data, _ := r.sqlCtx.IteratorHasNext(r.index)
return data != 0
}
func (r *ResultSetImpl) Close() (bool, ResultCode) {
data, code := r.sqlCtx.IteratorClose(r.index)
return data != 0, code
}