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  }