github.com/matrixorigin/matrixone@v1.2.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 int32) { 154 if decimal >= 0 { 155 mc.decimal = uint8(decimal) 156 } 157 } 158 159 func (mc *MysqlColumn) Flag() uint16 { 160 return mc.flag 161 } 162 163 func (mc *MysqlColumn) SetFlag(flag uint16) { 164 mc.flag = flag 165 } 166 167 func (mc *MysqlColumn) Charset() uint16 { 168 return mc.charset 169 } 170 171 func (mc *MysqlColumn) SetCharset(charset uint16) { 172 mc.charset = charset 173 } 174 175 func (mc *MysqlColumn) OrgName() string { 176 return mc.orgName 177 } 178 179 func (mc *MysqlColumn) SetOrgName(orgName string) { 180 mc.orgName = orgName 181 } 182 183 func (mc *MysqlColumn) OrgTable() string { 184 return mc.orgTable 185 } 186 187 func (mc *MysqlColumn) SetOrgTable(orgTable string) { 188 mc.orgTable = orgTable 189 } 190 191 func (mc *MysqlColumn) Table() string { 192 return mc.table 193 } 194 195 func (mc *MysqlColumn) SetTable(table string) { 196 mc.table = table 197 } 198 199 func (mc *MysqlColumn) Schema() string { 200 return mc.schema 201 } 202 203 func (mc *MysqlColumn) SetSchema(schema string) { 204 mc.schema = schema 205 } 206 207 func (mc *MysqlColumn) SetSigned(s bool) { 208 if s { 209 mc.flag = mc.flag &^ uint16(defines.UNSIGNED_FLAG) 210 } else { 211 mc.flag = mc.flag | uint16(defines.UNSIGNED_FLAG) 212 } 213 } 214 215 func (mc *MysqlColumn) IsSigned() bool { 216 return mc.flag&uint16(defines.UNSIGNED_FLAG) == 0 217 } 218 219 func (mc *MysqlColumn) SetAutoIncr(s bool) { 220 mc.auto_incr = s 221 } 222 223 func (mc *MysqlColumn) GetAutoIncr() bool { 224 return mc.auto_incr 225 } 226 227 // Discussion: for some MatrixOne types and Type.Scale value are needed for stringification, I think we 228 // need to add a field 229 // MoTypes []types.Type 230 // in this struct, what's your opinion on this matter?@Daviszhen 231 type MysqlResultSet struct { 232 //column information 233 Columns []Column 234 235 //column name --> column index 236 Name2Index map[string]uint64 237 238 //data 239 Data [][]interface{} 240 } 241 242 func (mrs *MysqlResultSet) AddColumn(column Column) uint64 { 243 mrs.Columns = append(mrs.Columns, column) 244 ret := mrs.GetColumnCount() - 1 245 246 if mrs.Name2Index == nil { 247 mrs.Name2Index = make(map[string]uint64) 248 } 249 250 name := column.Name() 251 mrs.Name2Index[name] = ret 252 253 return ret 254 } 255 256 func (mrs *MysqlResultSet) GetColumnCount() uint64 { 257 return uint64(len(mrs.Columns)) 258 } 259 260 func (mrs *MysqlResultSet) GetColumn(ctx context.Context, index uint64) (Column, error) { 261 if index < mrs.GetColumnCount() { 262 return mrs.Columns[index], nil 263 } else { 264 return nil, moerr.NewInternalError(ctx, "index valid column index %d ", index) 265 } 266 } 267 268 func (mrs *MysqlResultSet) AddRow(row []interface{}) uint64 { 269 mrs.Data = append(mrs.Data, row) 270 return mrs.GetRowCount() - 1 271 } 272 273 func (mrs *MysqlResultSet) GetRowCount() uint64 { 274 return uint64(len(mrs.Data)) 275 } 276 277 func (mrs *MysqlResultSet) GetRow(ctx context.Context, index uint64) ([]interface{}, error) { 278 if index < mrs.GetRowCount() { 279 return mrs.Data[index], nil 280 } else { 281 return nil, moerr.NewInternalError(ctx, "index valid row index %d ", index) 282 } 283 } 284 285 func (mrs *MysqlResultSet) GetValue(ctx context.Context, rindex uint64, cindex uint64) (interface{}, error) { 286 if row, err := mrs.GetRow(ctx, rindex); err != nil { 287 return nil, err 288 } else if cindex >= uint64(len(mrs.Columns)) { 289 return nil, moerr.NewInternalError(ctx, "index valid column index %d ", cindex) 290 } else { 291 return row[cindex], nil 292 } 293 } 294 295 // get the index of the column with name 296 func (mrs *MysqlResultSet) columnName2Index(ctx context.Context, name string) (uint64, error) { 297 if cindex, ok := mrs.Name2Index[name]; !ok { 298 return 0, moerr.NewInternalError(ctx, "column name does not exist. %s", name) 299 } else { 300 return cindex, nil 301 } 302 } 303 304 func (mrs *MysqlResultSet) GetValueByName(ctx context.Context, rindex uint64, colName string) (interface{}, error) { 305 if cindex, err := mrs.columnName2Index(ctx, colName); err != nil { 306 return nil, err 307 } else { 308 return mrs.GetValue(ctx, rindex, cindex) 309 } 310 } 311 312 // the value in position (rindex,cindex) is null or not 313 // return true - null ; false - not null 314 func (mrs *MysqlResultSet) ColumnIsNull(ctx context.Context, rindex, cindex uint64) (bool, error) { 315 if value, err := mrs.GetValue(ctx, rindex, cindex); err != nil { 316 return false, err 317 } else { 318 return value == nil, nil 319 } 320 } 321 322 // convert the value into int64 323 func (mrs *MysqlResultSet) GetInt64(ctx context.Context, rindex, cindex uint64) (int64, error) { 324 value, err := mrs.GetValue(ctx, rindex, cindex) 325 if err != nil { 326 return 0, err 327 } 328 329 switch v := value.(type) { 330 case bool: 331 if v { 332 return 1, nil 333 } else { 334 return 0, nil 335 } 336 case uint8: 337 return int64(v), nil 338 case uint16: 339 return int64(v), nil 340 case uint32: 341 return int64(v), nil 342 case uint64: 343 return int64(v), nil 344 case int8: 345 return int64(v), nil 346 case int16: 347 return int64(v), nil 348 case int32: 349 return int64(v), nil 350 case int64: 351 return int64(v), nil 352 case float32: 353 return int64(v), nil 354 case float64: 355 return int64(v), nil 356 case string: 357 return strconv.ParseInt(v, 10, 64) 358 case []byte: 359 return strconv.ParseInt(string(v), 10, 64) 360 case int: 361 return int64(v), nil 362 case uint: 363 return int64(v), nil 364 default: 365 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 366 } 367 } 368 369 // convert the value into uint64 370 func (mrs *MysqlResultSet) GetUint64(ctx context.Context, rindex, cindex uint64) (uint64, error) { 371 value, err := mrs.GetValue(ctx, rindex, cindex) 372 if err != nil { 373 return 0, err 374 } 375 376 switch v := value.(type) { 377 case bool: 378 if v { 379 return 1, nil 380 } else { 381 return 0, nil 382 } 383 case uint8: 384 return uint64(v), nil 385 case uint16: 386 return uint64(v), nil 387 case uint32: 388 return uint64(v), nil 389 case uint64: 390 return uint64(v), nil 391 case int8: 392 return uint64(v), nil 393 case int16: 394 return uint64(v), nil 395 case int32: 396 return uint64(v), nil 397 case int64: 398 return uint64(v), nil 399 case float32: 400 return uint64(v), nil 401 case float64: 402 return uint64(v), nil 403 case string: 404 return strconv.ParseUint(v, 10, 64) 405 case []byte: 406 return strconv.ParseUint(string(v), 10, 64) 407 case int: 408 return uint64(v), nil 409 case uint: 410 return uint64(v), nil 411 default: 412 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 413 } 414 } 415 416 // convert the value into Float64 417 func (mrs *MysqlResultSet) GetFloat64(ctx context.Context, rindex, cindex uint64) (float64, error) { 418 value, err := mrs.GetValue(ctx, rindex, cindex) 419 if err != nil { 420 return 0, err 421 } 422 423 switch v := value.(type) { 424 case bool: 425 if v { 426 return 1, nil 427 } else { 428 return 0, nil 429 } 430 case uint8: 431 return float64(v), nil 432 case uint16: 433 return float64(v), nil 434 case uint32: 435 return float64(v), nil 436 case uint64: 437 return float64(v), nil 438 case int8: 439 return float64(v), nil 440 case int16: 441 return float64(v), nil 442 case int32: 443 return float64(v), nil 444 case int64: 445 return float64(v), nil 446 case float32: 447 return float64(v), nil 448 case float64: 449 return float64(v), nil 450 case string: 451 return strconv.ParseFloat(v, 64) 452 case []byte: 453 return strconv.ParseFloat(string(v), 64) 454 case int: 455 return float64(v), nil 456 case uint: 457 return float64(v), nil 458 default: 459 return 0, moerr.NewInternalError(ctx, "unsupported type %d ", v) 460 } 461 } 462 463 // convert the value into string 464 func (mrs *MysqlResultSet) GetString(ctx context.Context, rindex, cindex uint64) (string, error) { 465 value, err := mrs.GetValue(ctx, rindex, cindex) 466 if err != nil { 467 return "", err 468 } 469 470 switch v := value.(type) { 471 case bool: 472 if v { 473 return "true", nil 474 } else { 475 return "false", nil 476 } 477 case uint8: 478 return strconv.FormatUint(uint64(v), 10), nil 479 case uint16: 480 return strconv.FormatUint(uint64(v), 10), nil 481 case uint32: 482 return strconv.FormatUint(uint64(v), 10), nil 483 case uint64: 484 return strconv.FormatUint(uint64(v), 10), nil 485 case int8: 486 return strconv.FormatInt(int64(v), 10), nil 487 case int16: 488 return strconv.FormatInt(int64(v), 10), nil 489 case int32: 490 return strconv.FormatInt(int64(v), 10), nil 491 case int64: 492 return strconv.FormatInt(int64(v), 10), nil 493 case float32: 494 return strconv.FormatFloat(float64(v), 'f', -1, 32), nil 495 case float64: 496 return strconv.FormatFloat(v, 'f', -1, 64), nil 497 case string: 498 return v, nil 499 case []byte: 500 return string(v), nil 501 case []float32: 502 return types.ArrayToString[float32](v), nil 503 case []float64: 504 return types.ArrayToString[float64](v), nil 505 case int: 506 return strconv.FormatInt(int64(v), 10), nil 507 case uint: 508 return strconv.FormatUint(uint64(v), 10), nil 509 case types.Time: 510 return v.String(), nil 511 case types.Datetime: 512 return v.String(), nil 513 case bytejson.ByteJson: 514 return v.String(), nil 515 case types.Uuid: 516 return v.ToString(), nil 517 case types.Blockid: 518 return v.String(), nil 519 case types.TS: 520 return v.ToString(), nil 521 case types.Enum: 522 return strconv.FormatUint(uint64(v), 10), nil 523 default: 524 return "", moerr.NewInternalError(ctx, "unsupported type %d ", v) 525 } 526 } 527 528 // the result of the execution 529 type MysqlExecutionResult struct { 530 status uint16 531 insertID uint64 532 affectedRows uint64 533 warnings uint16 534 535 mrs *MysqlResultSet 536 } 537 538 func (mer *MysqlExecutionResult) Mrs() *MysqlResultSet { 539 return mer.mrs 540 } 541 542 func (mer *MysqlExecutionResult) SetMrs(mrs *MysqlResultSet) { 543 mer.mrs = mrs 544 } 545 546 func (mer *MysqlExecutionResult) Warnings() uint16 { 547 return mer.warnings 548 } 549 550 func (mer *MysqlExecutionResult) SetWarnings(warnings uint16) { 551 mer.warnings = warnings 552 } 553 554 func (mer *MysqlExecutionResult) AffectedRows() uint64 { 555 return mer.affectedRows 556 } 557 558 func (mer *MysqlExecutionResult) SetAffectedRows(affectedRows uint64) { 559 mer.affectedRows = affectedRows 560 } 561 562 func (mer *MysqlExecutionResult) InsertID() uint64 { 563 return mer.insertID 564 } 565 566 func (mer *MysqlExecutionResult) SetInsertID(insertID uint64) { 567 mer.insertID = insertID 568 } 569 570 func (mer *MysqlExecutionResult) Status() uint16 { 571 return mer.status 572 } 573 574 func (mer *MysqlExecutionResult) SetStatus(status uint16) { 575 mer.status = status 576 } 577 578 func NewMysqlExecutionResult(status uint16, insertid, rows uint64, warnings uint16, mrs *MysqlResultSet) *MysqlExecutionResult { 579 return &MysqlExecutionResult{ 580 status: status, 581 insertID: insertid, 582 affectedRows: rows, 583 warnings: warnings, 584 mrs: mrs, 585 } 586 }