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  }