Skip to content

Commit 8fc3fd3

Browse files
authored
table session and table session pool (#111)
* table session and table session pool * fix cluster config * fix enableRPCCompression in reconnect * add ut * add session pool tests * fix atomic usage to 1.13 version * update common.go * add license * fix tablet test * add doc * add comment * add comment * return success code when tablet is empty
1 parent 223b9e0 commit 8fc3fd3

File tree

14 files changed

+3082
-859
lines changed

14 files changed

+3082
-859
lines changed

client/bitmap.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ var UnmarkBitUtil = []byte{
3737
}
3838

3939
func NewBitMap(size int) *BitMap {
40+
// Need to maintain consistency with the calculation method on the IoTDB side.
4041
bitMap := &BitMap{
4142
size: size,
42-
bits: make([]byte, (size+7)/8),
43+
bits: make([]byte, size/8+1),
4344
}
4445
return bitMap
4546
}

client/rpcdataset.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ func (s *IoTDBRpcDataSet) getColumnType(columnName string) TSDataType {
8989
return s.columnTypeDeduplicatedList[s.getColumnIndex(columnName)]
9090
}
9191

92+
func (s *IoTDBRpcDataSet) isNullWithColumnName(columnName string) bool {
93+
return s.isNull(int(s.getColumnIndex(columnName)), s.rowsIndex-1)
94+
}
95+
9296
func (s *IoTDBRpcDataSet) isNull(columnIndex int, rowIndex int) bool {
9397
if s.closed {
9498
return true

client/session.go

Lines changed: 107 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ const (
4242
DefaultTimeZone = "Asia/Shanghai"
4343
DefaultFetchSize = 1024
4444
DefaultConnectRetryMax = 3
45+
TreeSqlDialect = "tree"
46+
TableSqlDialect = "table"
47+
)
48+
49+
type Version string
50+
51+
const (
52+
V_0_12 = Version("V_0_12")
53+
V_0_13 = Version("V_0_13")
54+
V_1_0 = Version("V_1_0")
55+
DEFAULT_VERSION = V_1_0
4556
)
4657

4758
var errLength = errors.New("deviceIds, times, measurementsList and valuesList's size should be equal")
@@ -54,6 +65,9 @@ type Config struct {
5465
FetchSize int32
5566
TimeZone string
5667
ConnectRetryMax int
68+
sqlDialect string
69+
Version Version
70+
Database string
5771
}
5872

5973
type Session struct {
@@ -62,6 +76,7 @@ type Session struct {
6276
sessionId int64
6377
trans thrift.TTransport
6478
requestStatementId int64
79+
protocolFactory thrift.TProtocolFactory
6580
}
6681

6782
type endPoint struct {
@@ -83,7 +98,6 @@ func (s *Session) Open(enableRPCCompression bool, connectionTimeoutInMs int) err
8398
s.config.ConnectRetryMax = DefaultConnectRetryMax
8499
}
85100

86-
var protocolFactory thrift.TProtocolFactory
87101
var err error
88102

89103
// in thrift 0.14.1, this func returns two values; in thrift 0.15.0, it returns one.
@@ -99,16 +113,22 @@ func (s *Session) Open(enableRPCCompression bool, connectionTimeoutInMs int) err
99113
return err
100114
}
101115
}
102-
if enableRPCCompression {
103-
protocolFactory = thrift.NewTCompactProtocolFactory()
104-
} else {
105-
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
106-
}
107-
iprot := protocolFactory.GetProtocol(s.trans)
108-
oprot := protocolFactory.GetProtocol(s.trans)
116+
s.protocolFactory = getProtocolFactory(enableRPCCompression)
117+
iprot := s.protocolFactory.GetProtocol(s.trans)
118+
oprot := s.protocolFactory.GetProtocol(s.trans)
109119
s.client = rpc.NewIClientRPCServiceClient(thrift.NewTStandardClient(iprot, oprot))
110120
req := rpc.TSOpenSessionReq{ClientProtocol: rpc.TSProtocolVersion_IOTDB_SERVICE_PROTOCOL_V3, ZoneId: s.config.TimeZone, Username: s.config.UserName,
111121
Password: &s.config.Password}
122+
req.Configuration = make(map[string]string)
123+
req.Configuration["sql_dialect"] = s.config.sqlDialect
124+
if s.config.Version == "" {
125+
req.Configuration["version"] = string(DEFAULT_VERSION)
126+
} else {
127+
req.Configuration["version"] = string(s.config.Version)
128+
}
129+
if s.config.Database != "" {
130+
req.Configuration["db"] = s.config.Database
131+
}
112132
resp, err := s.client.OpenSession(context.Background(), &req)
113133
if err != nil {
114134
return err
@@ -125,14 +145,8 @@ type ClusterConfig struct {
125145
FetchSize int32
126146
TimeZone string
127147
ConnectRetryMax int
128-
}
129-
130-
type ClusterSession struct {
131-
config *ClusterConfig
132-
client *rpc.IClientRPCServiceClient
133-
sessionId int64
134-
trans thrift.TTransport
135-
requestStatementId int64
148+
sqlDialect string
149+
Database string
136150
}
137151

138152
func (s *Session) OpenCluster(enableRPCCompression bool) error {
@@ -147,19 +161,24 @@ func (s *Session) OpenCluster(enableRPCCompression bool) error {
147161
s.config.ConnectRetryMax = DefaultConnectRetryMax
148162
}
149163

150-
var protocolFactory thrift.TProtocolFactory
151164
var err error
152165

153-
if enableRPCCompression {
154-
protocolFactory = thrift.NewTCompactProtocolFactory()
155-
} else {
156-
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
157-
}
158-
iprot := protocolFactory.GetProtocol(s.trans)
159-
oprot := protocolFactory.GetProtocol(s.trans)
166+
s.protocolFactory = getProtocolFactory(enableRPCCompression)
167+
iprot := s.protocolFactory.GetProtocol(s.trans)
168+
oprot := s.protocolFactory.GetProtocol(s.trans)
160169
s.client = rpc.NewIClientRPCServiceClient(thrift.NewTStandardClient(iprot, oprot))
161170
req := rpc.TSOpenSessionReq{ClientProtocol: rpc.TSProtocolVersion_IOTDB_SERVICE_PROTOCOL_V3, ZoneId: s.config.TimeZone, Username: s.config.UserName,
162171
Password: &s.config.Password}
172+
req.Configuration = make(map[string]string)
173+
req.Configuration["sql_dialect"] = s.config.sqlDialect
174+
if s.config.Version == "" {
175+
req.Configuration["version"] = string(DEFAULT_VERSION)
176+
} else {
177+
req.Configuration["version"] = string(s.config.Version)
178+
}
179+
if s.config.Database != "" {
180+
req.Configuration["db"] = s.config.Database
181+
}
163182

164183
resp, err := s.client.OpenSession(context.Background(), &req)
165184
if err != nil {
@@ -170,14 +189,22 @@ func (s *Session) OpenCluster(enableRPCCompression bool) error {
170189
return err
171190
}
172191

173-
func (s *Session) Close() (r *common.TSStatus, err error) {
192+
func getProtocolFactory(enableRPCCompression bool) thrift.TProtocolFactory {
193+
if enableRPCCompression {
194+
return thrift.NewTCompactProtocolFactoryConf(&thrift.TConfiguration{})
195+
} else {
196+
return thrift.NewTBinaryProtocolFactoryConf(&thrift.TConfiguration{})
197+
}
198+
}
199+
200+
func (s *Session) Close() error {
174201
req := rpc.NewTSCloseSessionReq()
175202
req.SessionId = s.sessionId
176-
_, err = s.client.CloseSession(context.Background(), req)
203+
_, err := s.client.CloseSession(context.Background(), req)
177204
if err != nil {
178-
return nil, err
205+
return err
179206
}
180-
return nil, s.trans.Close()
207+
return s.trans.Close()
181208
}
182209

183210
/*
@@ -453,10 +480,17 @@ func (s *Session) ExecuteNonQueryStatement(sql string) (r *common.TSStatus, err
453480
resp, err = s.client.ExecuteStatement(context.Background(), &request)
454481
}
455482
}
483+
if resp.IsSetDatabase() {
484+
s.changeDatabase(*resp.Database)
485+
}
456486

457487
return resp.Status, err
458488
}
459489

490+
func (s *Session) changeDatabase(database string) {
491+
s.config.Database = database
492+
}
493+
460494
func (s *Session) ExecuteQueryStatement(sql string, timeoutMs *int64) (*SessionDataSet, error) {
461495
request := rpc.TSExecuteStatementReq{SessionId: s.sessionId, Statement: sql, StatementId: s.requestStatementId,
462496
FetchSize: &s.config.FetchSize, Timeout: timeoutMs}
@@ -613,7 +647,7 @@ func (d *deviceData) Swap(i, j int) {
613647
// InsertRecordsOfOneDevice Insert multiple rows, which can reduce the overhead of network. This method is just like jdbc
614648
// executeBatch, we pack some insert request in batch and send them to server. If you want improve
615649
// your performance, please see insertTablet method
616-
// Each row is independent, which could have different deviceId, time, number of measurements
650+
// Each row is independent, which could have different insertTargetName, time, number of measurements
617651
func (s *Session) InsertRecordsOfOneDevice(deviceId string, timestamps []int64, measurementsSlice [][]string, dataTypesSlice [][]TSDataType, valuesSlice [][]interface{}, sorted bool) (r *common.TSStatus, err error) {
618652
length := len(timestamps)
619653
if len(measurementsSlice) != length || len(dataTypesSlice) != length || len(valuesSlice) != length {
@@ -873,7 +907,7 @@ func (s *Session) genInsertTabletsReq(tablets []*Tablet, isAligned bool) (*rpc.T
873907
sizeList = make([]int32, length)
874908
)
875909
for index, tablet := range tablets {
876-
deviceIds[index] = tablet.deviceId
910+
deviceIds[index] = tablet.insertTargetName
877911
measurementsList[index] = tablet.GetMeasurements()
878912

879913
values, err := tablet.getValuesBytes()
@@ -1009,13 +1043,35 @@ func valuesToBytes(dataTypes []TSDataType, values []interface{}) ([]byte, error)
10091043
return buff.Bytes(), nil
10101044
}
10111045

1046+
func (s *Session) insertRelationalTablet(tablet *Tablet) (r *common.TSStatus, err error) {
1047+
if tablet.Len() == 0 {
1048+
return &common.TSStatus{Code: SuccessStatus}, nil
1049+
}
1050+
request, err := s.genTSInsertTabletReq(tablet, true, true)
1051+
if err != nil {
1052+
return nil, err
1053+
}
1054+
request.ColumnCategories = tablet.getColumnCategories()
1055+
1056+
r, err = s.client.InsertTablet(context.Background(), request)
1057+
1058+
if err != nil && r == nil {
1059+
if s.reconnect() {
1060+
request.SessionId = s.sessionId
1061+
r, err = s.client.InsertTablet(context.Background(), request)
1062+
}
1063+
}
1064+
1065+
return r, err
1066+
}
1067+
10121068
func (s *Session) InsertTablet(tablet *Tablet, sorted bool) (r *common.TSStatus, err error) {
10131069
if !sorted {
10141070
if err := tablet.Sort(); err != nil {
10151071
return nil, err
10161072
}
10171073
}
1018-
request, err := s.genTSInsertTabletReq(tablet, false)
1074+
request, err := s.genTSInsertTabletReq(tablet, false, false)
10191075
if err != nil {
10201076
return nil, err
10211077
}
@@ -1038,7 +1094,7 @@ func (s *Session) InsertAlignedTablet(tablet *Tablet, sorted bool) (r *common.TS
10381094
return nil, err
10391095
}
10401096
}
1041-
request, err := s.genTSInsertTabletReq(tablet, true)
1097+
request, err := s.genTSInsertTabletReq(tablet, true, false)
10421098
if err != nil {
10431099
return nil, err
10441100
}
@@ -1055,17 +1111,18 @@ func (s *Session) InsertAlignedTablet(tablet *Tablet, sorted bool) (r *common.TS
10551111
return r, err
10561112
}
10571113

1058-
func (s *Session) genTSInsertTabletReq(tablet *Tablet, isAligned bool) (*rpc.TSInsertTabletReq, error) {
1114+
func (s *Session) genTSInsertTabletReq(tablet *Tablet, isAligned bool, writeToTable bool) (*rpc.TSInsertTabletReq, error) {
10591115
if values, err := tablet.getValuesBytes(); err == nil {
10601116
request := &rpc.TSInsertTabletReq{
10611117
SessionId: s.sessionId,
1062-
PrefixPath: tablet.deviceId,
1118+
PrefixPath: tablet.insertTargetName,
10631119
Measurements: tablet.GetMeasurements(),
10641120
Values: values,
10651121
Timestamps: tablet.GetTimestampBytes(),
10661122
Types: tablet.getDataTypes(),
10671123
Size: int32(tablet.RowSize),
10681124
IsAligned: &isAligned,
1125+
WriteToTable: &writeToTable,
10691126
}
10701127
return request, nil
10711128
} else {
@@ -1078,6 +1135,11 @@ func (s *Session) GetSessionId() int64 {
10781135
}
10791136

10801137
func NewSession(config *Config) Session {
1138+
config.sqlDialect = TreeSqlDialect
1139+
return newSessionWithSpecifiedSqlDialect(config)
1140+
}
1141+
1142+
func newSessionWithSpecifiedSqlDialect(config *Config) Session {
10811143
endPoint := endPoint{}
10821144
endPoint.Host = config.Host
10831145
endPoint.Port = config.Port
@@ -1086,6 +1148,11 @@ func NewSession(config *Config) Session {
10861148
}
10871149

10881150
func NewClusterSession(clusterConfig *ClusterConfig) Session {
1151+
clusterConfig.sqlDialect = TreeSqlDialect
1152+
return newClusterSessionWithSqlDialect(clusterConfig)
1153+
}
1154+
1155+
func newClusterSessionWithSqlDialect(clusterConfig *ClusterConfig) Session {
10891156
session := Session{}
10901157
node := endPoint{}
10911158
for i := 0; i < len(clusterConfig.NodeUrls); i++ {
@@ -1107,7 +1174,7 @@ func NewClusterSession(clusterConfig *ClusterConfig) Session {
11071174
log.Println(err)
11081175
} else {
11091176
session.config = getConfig(e.Value.(endPoint).Host, e.Value.(endPoint).Port,
1110-
clusterConfig.UserName, clusterConfig.Password, clusterConfig.FetchSize, clusterConfig.TimeZone, clusterConfig.ConnectRetryMax)
1177+
clusterConfig.UserName, clusterConfig.Password, clusterConfig.FetchSize, clusterConfig.TimeZone, clusterConfig.ConnectRetryMax, clusterConfig.Database, clusterConfig.sqlDialect)
11111178
break
11121179
}
11131180
}
@@ -1148,10 +1215,8 @@ func (s *Session) initClusterConn(node endPoint) error {
11481215
s.config.ConnectRetryMax = DefaultConnectRetryMax
11491216
}
11501217

1151-
var protocolFactory thrift.TProtocolFactory
1152-
protocolFactory = thrift.NewTBinaryProtocolFactoryDefault()
1153-
iprot := protocolFactory.GetProtocol(s.trans)
1154-
oprot := protocolFactory.GetProtocol(s.trans)
1218+
iprot := s.protocolFactory.GetProtocol(s.trans)
1219+
oprot := s.protocolFactory.GetProtocol(s.trans)
11551220
s.client = rpc.NewIClientRPCServiceClient(thrift.NewTStandardClient(iprot, oprot))
11561221
req := rpc.TSOpenSessionReq{ClientProtocol: rpc.TSProtocolVersion_IOTDB_SERVICE_PROTOCOL_V3, ZoneId: s.config.TimeZone, Username: s.config.UserName,
11571222
Password: &s.config.Password}
@@ -1166,7 +1231,7 @@ func (s *Session) initClusterConn(node endPoint) error {
11661231

11671232
}
11681233

1169-
func getConfig(host string, port string, userName string, passWord string, fetchSize int32, timeZone string, connectRetryMax int) *Config {
1234+
func getConfig(host string, port string, userName string, passWord string, fetchSize int32, timeZone string, connectRetryMax int, database string, sqlDialect string) *Config {
11701235
return &Config{
11711236
Host: host,
11721237
Port: port,
@@ -1175,6 +1240,8 @@ func getConfig(host string, port string, userName string, passWord string, fetch
11751240
FetchSize: fetchSize,
11761241
TimeZone: timeZone,
11771242
ConnectRetryMax: connectRetryMax,
1243+
sqlDialect: sqlDialect,
1244+
Database: database,
11781245
}
11791246
}
11801247

client/sessiondataset.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ func (s *SessionDataSet) GetText(columnName string) string {
4646
return s.ioTDBRpcDataSet.getText(columnName)
4747
}
4848

49+
func (s *SessionDataSet) IsNull(columnName string) bool {
50+
return s.ioTDBRpcDataSet.isNullWithColumnName(columnName)
51+
}
52+
4953
func (s *SessionDataSet) GetBool(columnName string) bool {
5054
return s.ioTDBRpcDataSet.getBool(columnName)
5155
}

0 commit comments

Comments
 (0)