github.com/matrixorigin/matrixone@v0.7.0/pkg/frontend/resultset.go (about) 1 // Copyright 2021 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package frontend 16 17 import ( 18 "context" 19 "strconv" 20 21 "github.com/matrixorigin/matrixone/pkg/common/moerr" 22 "github.com/matrixorigin/matrixone/pkg/container/bytejson" 23 24 "github.com/matrixorigin/matrixone/pkg/container/types" 25 26 "github.com/matrixorigin/matrixone/pkg/defines" 27 ) 28 29 type Column interface { 30 SetName(string) 31 Name() string 32 33 //data type: MYSQL_TYPE_XXXX 34 SetColumnType(defines.MysqlType) 35 ColumnType() defines.MysqlType 36 37 //the max count of spaces 38 SetLength(uint32) 39 Length() uint32 40 41 //unsigned / signed for digital types 42 //default: signed 43 //true: signed; false: unsigned 44 SetSigned(bool) 45 IsSigned() bool 46 } 47 48 type ColumnImpl struct { 49 //the name of the column 50 name string 51 52 //the data type of the column 53 columnType defines.MysqlType 54 55 //maximum length in bytes of the field 56 length uint32 57 } 58 59 func (ci *ColumnImpl) ColumnType() defines.MysqlType { 60 return ci.columnType 61 } 62 63 func (ci *ColumnImpl) SetColumnType(colType defines.MysqlType) { 64 ci.columnType = colType 65 } 66 67 func (ci *ColumnImpl) Name() string { 68 return ci.name 69 } 70 71 func (ci *ColumnImpl) SetName(name string) { 72 ci.name = name 73 } 74 75 func (ci *ColumnImpl) SetLength(l uint32) { 76 ci.length = l 77 } 78 func (ci *ColumnImpl) Length() uint32 { 79 return ci.length 80 } 81 82 type ResultSet interface { 83 //Add a column definition 84 //return the index of column (start from 0) 85 AddColumn(Column) uint64 86 87 //the Count of the Column 88 GetColumnCount() uint64 89 90 //get the i th column 91 GetColumn(context.Context, uint64) (Column, error) 92 93 //Add a data row 94 //return the index of row (start from 0) 95 AddRow([]interface{}) uint64 96 97 //the count of the data row 98 GetRowCount() uint64 99 100 //get the i th data row 101 GetRow(context.Context, uint64) ([]interface{}, error) 102 103 //get the data of row i, column j 104 GetValue(context.Context, uint64, uint64) (interface{}, error) 105 106 //get the data of row i, column 107 GetValueByName(context.Context, uint64, string) (interface{}, error) 108 } 109 110 type MysqlColumn struct { 111 ColumnImpl 112 113 //schema name 114 schema string 115 116 //virtual table name 117 table string 118 119 //physical table name 120 orgTable string 121 122 //physical column name 123 orgName string 124 125 //the column character. Actually, it is the collation id 126 charset uint16 127 128 //flags 129 flag uint16 130 131 //auto_incr 132 auto_incr bool 133 134 //max shown decimal digits 135 decimal uint8 136 137 //default value 138 defaultValue []byte 139 } 140 141 func (mc *MysqlColumn) DefaultValue() []byte { 142 return mc.defaultValue 143 } 144 145 func (mc *MysqlColumn) SetDefaultValue(defaultValue []byte) { 146 mc.defaultValue = defaultValue 147 } 148 149 func (mc *MysqlColumn) Decimal() uint8 { 150 return mc.decimal 151 } 152 153 func (mc *MysqlColumn) SetDecimal(decimal uint8) { 154 if mc.columnType == defines.MYSQL_TYPE_FLOAT || mc.columnType == defines.MYSQL_TYPE_DOUBLE { 155 mc.decimal = 31 156 return 157 } 158 mc.decimal = decimal 159 } 160 161 func (mc *MysqlColumn) Flag() uint16 { 162 return mc.flag 163 } 164 165 func (mc *MysqlColumn) SetFlag(flag uint16) { 166 mc.flag = flag 167 } 168 169 func (mc *MysqlColumn) Charset() uint16 { 170 return mc.charset 171 } 172 173 func (mc *MysqlColumn) SetCharset(charset uint16) { 174 mc.charset = charset 175 } 176 177 func (mc *MysqlColumn) OrgName() string { 178 return mc.orgName 179 } 180 181 func (mc *MysqlColumn) SetOrgName(orgName string) { 182 mc.orgName = orgName 183 } 184 185 func (mc *MysqlColumn) OrgTable() string { 186 return mc.orgTable 187 } 188 189 func (mc *MysqlColumn) SetOrgTable(orgTable string) { 190 mc.orgTable = orgTable 191 } 192 193 func (mc *MysqlColumn) Table() string { 194 return mc.table 195 } 196 197 func (mc *MysqlColumn) SetTable(table string) { 198 mc.table = table 199 } 200 201 func (mc *MysqlColumn) Schema() string { 202 return mc.schema 203 } 204 205 func (mc *MysqlColumn) SetSchema(schema string) { 206 mc.schema = schema 207 } 208 209 func (mc *MysqlColumn) SetSigned(s bool) { 210 if s { 211 mc.flag = mc.flag &^ uint16(defines.UNSIGNED_FLAG) 212 } else { 213 mc.flag = mc.flag | uint16(defines.UNSIGNED_FLAG) 214 } 215 } 216 217 func (mc *MysqlColumn) IsSigned() bool { 218 return mc.flag&uint16(defines.UNSIGNED_FLAG) == 0 219 } 220 221 func (mc *MysqlColumn) SetAutoIncr(s bool) { 222 mc.auto_incr = s 223 } 224 225 func (mc *MysqlColumn) GetAutoIncr() bool { 226 return mc.auto_incr 227 } 228 229 // Discussion: for some MatrixOne types, the Type.Precision and Type.Scale value are needed for stringification, I think we 230 // need to add a field 231 // MoTypes []types.Type 232 // in this struct, what's your opinion on this matter?@Daviszhen 233 type MysqlResultSet struct { 234 //column information 235 Columns []Column 236 237 //column name --> column index 238 Name2Index map[string]uint64 239 240 //data 241 Data [][]interface{} 242 } 243 244 func (mrs *MysqlResultSet) AddColumn(column Column) uint64 { 245 mrs.Columns = append(mrs.Columns, column) 246 ret := mrs.GetColumnCount() - 1 247 248 if mrs.Name2Index == nil { 249 mrs.Name2Index = make(map[string]uint64) 250 } 251 252 name := column.Name() 253 mrs.Name2Index[name] = ret 254 255 return ret 256 } 257 258 func (mrs *MysqlResultSet) GetColumnCount() uint64 { 259 return uint64(len(mrs.Columns)) 260 } 261 262 func (mrs *MysqlResultSet) GetColumn(ctx context.Context, index uint64) (Column, error) { 263 if index < mrs.GetColumnCount() { 264 return mrs.Columns[index], nil 265 } else { 266 return nil, moerr.NewInternalError(ctx, "index valid column index %d ", index) 267 } 268 } 269 270 func (mrs *MysqlResultSet) AddRow(row []interface{}) uint64 { 271 mrs.Data = append(mrs.Data, row) 272 return mrs.GetRowCount() - 1 273 } 274 275 func (mrs *MysqlResultSet) GetRowCount() uint64 { 276 return uint64(len(mrs.Data)) 277 } 278 279 func (mrs *MysqlResultSet) GetRow(ctx context.Context, index uint64) ([]interface{}, error) { 280 if index < mrs.GetRowCount() { 281 return mrs.Data[index], nil 282 } else { 283 return nil, moerr.NewInternalError(ctx, "index valid row index %d ", index) 284 } 285 } 286 287 func (mrs *MysqlResultSet) GetValue(ctx context.Context, rindex uint64, cindex uint64) (interface{}, error) { 288 if row, err := mrs.GetRow(ctx, rindex); err != nil { 289 return nil, err 290 } else if cindex >= uint64(len(mrs.Columns)) { 291 return nil, moerr.NewInternalError(ctx, "index valid column index %d ", cindex) 292 } else { 293 return row[cindex], nil 294 } 295 } 296 297 // get the index of the column with name 298 func (mrs *MysqlResultSet) columnName2Index(ctx context.Context, name string) (uint64, error) { 299 if cindex, ok := mrs.Name2Index[name]; !ok { 300 return 0, moerr.NewInternalError(ctx, "column name does not exist. %s", name) 301 } else { 302 return cindex, nil 303 } 304 } 305 306 func (mrs *MysqlResultSet) GetValueByName(ctx context.Context, rindex uint64, colName string) (interface{}, error) { 307 if cindex, err := mrs.columnName2Index(ctx, colName); err != nil { 308 return nil, err 309 } else { 310 return mrs.GetValue(ctx, rindex, cindex) 311 } 312 } 313 314 // the value in position (rindex,cindex) is null or not 315 // return true - null ; false - not null 316 func (mrs *MysqlResultSet) ColumnIsNull(ctx context.Context, rindex, cindex uint64) (bool, error) { 317 if value, err := mrs.GetValue(ctx, rindex, cindex); err != nil { 318 return false, err 319 } else { 320 return value == nil, nil 321 } 322 } 323 324 // convert the value into int64 325 func (mrs *MysqlResultSet) GetInt64(ctx context.Context, rindex, cindex uint64) (int64, error) { 326 value, err := mrs.GetValue(ctx, rindex, cindex) 327 if err != nil { 328 return 0, err 329 } 330 331 switch v := value.(type) { 332 case bool: 333 if v { 334 return 1, nil 335 } else { 336 return 0, nil 337 } 338 case uint8: 339 return int64(v), nil 340 case uint16: 341 return int64(v), nil 342 case uint32: 343 return int64(v), nil 344 case uint64: 345 return int64(v), nil 346 case int8: 347 return int64(v), nil 348 case int16: 349 return int64(v), nil 350 case int32: 351 return int64(v), nil 352 case int64: 353 return int64(v), nil 354 case float32: 355 return int64(v), nil 356 case float64: 357 return int64(v), nil 358 case string: 359 return strconv.ParseInt(v, 10, 64) 360 case []byte: 361 return strconv.ParseInt(string(v), 10, 64) 362 case int: 363 return int64(v), nil 364 case uint: 365 return int64(v), nil 366 default: 367 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 368 } 369 } 370 371 // convert the value into uint64 372 func (mrs *MysqlResultSet) GetUint64(ctx context.Context, rindex, cindex uint64) (uint64, error) { 373 value, err := mrs.GetValue(ctx, rindex, cindex) 374 if err != nil { 375 return 0, err 376 } 377 378 switch v := value.(type) { 379 case bool: 380 if v { 381 return 1, nil 382 } else { 383 return 0, nil 384 } 385 case uint8: 386 return uint64(v), nil 387 case uint16: 388 return uint64(v), nil 389 case uint32: 390 return uint64(v), nil 391 case uint64: 392 return uint64(v), nil 393 case int8: 394 return uint64(v), nil 395 case int16: 396 return uint64(v), nil 397 case int32: 398 return uint64(v), nil 399 case int64: 400 return uint64(v), nil 401 case float32: 402 return uint64(v), nil 403 case float64: 404 return uint64(v), nil 405 case string: 406 return strconv.ParseUint(v, 10, 64) 407 case []byte: 408 return strconv.ParseUint(string(v), 10, 64) 409 case int: 410 return uint64(v), nil 411 case uint: 412 return uint64(v), nil 413 default: 414 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 415 } 416 } 417 418 // convert the value into Float64 419 func (mrs *MysqlResultSet) GetFloat64(ctx context.Context, rindex, cindex uint64) (float64, error) { 420 value, err := mrs.GetValue(ctx, rindex, cindex) 421 if err != nil { 422 return 0, err 423 } 424 425 switch v := value.(type) { 426 case bool: 427 if v { 428 return 1, nil 429 } else { 430 return 0, nil 431 } 432 case uint8: 433 return float64(v), nil 434 case uint16: 435 return float64(v), nil 436 case uint32: 437 return float64(v), nil 438 case uint64: 439 return float64(v), nil 440 case int8: 441 return float64(v), nil 442 case int16: 443 return float64(v), nil 444 case int32: 445 return float64(v), nil 446 case int64: 447 return float64(v), nil 448 case float32: 449 return float64(v), nil 450 case float64: 451 return float64(v), nil 452 case string: 453 return strconv.ParseFloat(v, 64) 454 case []byte: 455 return strconv.ParseFloat(string(v), 64) 456 case int: 457 return float64(v), nil 458 case uint: 459 return float64(v), nil 460 default: 461 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 462 } 463 } 464 465 // convert the value into string 466 func (mrs *MysqlResultSet) GetString(ctx context.Context, rindex, cindex uint64) (string, error) { 467 value, err := mrs.GetValue(ctx, rindex, cindex) 468 if err != nil { 469 return "", err 470 } 471 472 switch v := value.(type) { 473 case bool: 474 if v { 475 return "true", nil 476 } else { 477 return "false", nil 478 } 479 case uint8: 480 return strconv.FormatUint(uint64(v), 10), nil 481 case uint16: 482 return strconv.FormatUint(uint64(v), 10), nil 483 case uint32: 484 return strconv.FormatUint(uint64(v), 10), nil 485 case uint64: 486 return strconv.FormatUint(uint64(v), 10), nil 487 case int8: 488 return strconv.FormatInt(int64(v), 10), nil 489 case int16: 490 return strconv.FormatInt(int64(v), 10), nil 491 case int32: 492 return strconv.FormatInt(int64(v), 10), nil 493 case int64: 494 return strconv.FormatInt(int64(v), 10), nil 495 case float32: 496 return strconv.FormatFloat(float64(v), 'f', -1, 32), nil 497 case float64: 498 return strconv.FormatFloat(v, 'f', -1, 32), nil 499 case string: 500 return v, nil 501 case []byte: 502 return string(v), nil 503 case int: 504 return strconv.FormatInt(int64(v), 10), nil 505 case uint: 506 return strconv.FormatUint(uint64(v), 10), nil 507 case types.Time: 508 return v.String(), nil 509 case types.Datetime: 510 return v.String(), nil 511 case bytejson.ByteJson: 512 return v.String(), nil 513 case types.Uuid: 514 return v.ToString(), nil 515 default: 516 return "", moerr.NewInternalError(ctx, "unsupported type %d ", v) 517 } 518 } 519 520 // the result of the execution 521 type MysqlExecutionResult struct { 522 status uint16 523 insertID uint64 524 affectedRows uint64 525 warnings uint16 526 527 mrs *MysqlResultSet 528 } 529 530 func (mer *MysqlExecutionResult) Mrs() *MysqlResultSet { 531 return mer.mrs 532 } 533 534 func (mer *MysqlExecutionResult) SetMrs(mrs *MysqlResultSet) { 535 mer.mrs = mrs 536 } 537 538 func (mer *MysqlExecutionResult) Warnings() uint16 { 539 return mer.warnings 540 } 541 542 func (mer *MysqlExecutionResult) SetWarnings(warnings uint16) { 543 mer.warnings = warnings 544 } 545 546 func (mer *MysqlExecutionResult) AffectedRows() uint64 { 547 return mer.affectedRows 548 } 549 550 func (mer *MysqlExecutionResult) SetAffectedRows(affectedRows uint64) { 551 mer.affectedRows = affectedRows 552 } 553 554 func (mer *MysqlExecutionResult) InsertID() uint64 { 555 return mer.insertID 556 } 557 558 func (mer *MysqlExecutionResult) SetInsertID(insertID uint64) { 559 mer.insertID = insertID 560 } 561 562 func (mer *MysqlExecutionResult) Status() uint16 { 563 return mer.status 564 } 565 566 func (mer *MysqlExecutionResult) SetStatus(status uint16) { 567 mer.status = status 568 } 569 570 func NewMysqlExecutionResult(status uint16, insertid, rows uint64, warnings uint16, mrs *MysqlResultSet) *MysqlExecutionResult { 571 return &MysqlExecutionResult{ 572 status: status, 573 insertID: insertid, 574 affectedRows: rows, 575 warnings: warnings, 576 mrs: mrs, 577 } 578 }