github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/builtin/unary/infomation_function.go (about)

     1  // Copyright 2022 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 unary
    16  
    17  import (
    18  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    19  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    21  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    22  )
    23  
    24  /*
    25  These functions get information from the session and system status.
    26  */
    27  
    28  func adapter(vectors []*vector.Vector,
    29  	proc *process.Process,
    30  	resultType types.Type,
    31  	parameterCount int,
    32  	evaluateMemoryCapacityForJobFunc func(proc *process.Process, params ...interface{}) (int, error),
    33  	jobFunc func(proc *process.Process, params ...interface{}) (interface{}, error),
    34  ) (*vector.Vector, error) {
    35  	if parameterCount == 0 {
    36  		//XXX step 1 is not needed now.
    37  		//step 1: evaluate the capacity for result vector
    38  
    39  		//step 2: allocate the memory for the result
    40  		var svals []string
    41  		var uvals []uint64
    42  		var resultSpace interface{}
    43  		if resultType.IsString() {
    44  			svals = make([]string, 1)
    45  			resultSpace = svals
    46  		} else {
    47  			uvals = make([]uint64, 1)
    48  			resultSpace = uvals
    49  		}
    50  		//step 3: evaluate the function and get the result
    51  		result, err := jobFunc(proc, resultSpace)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		//step 4: fill the result vector
    56  		if result == nil {
    57  			return vector.NewConstNull(resultType, 1), nil
    58  		} else if resultType.IsString() {
    59  			return vector.NewConstString(resultType, 1, svals[0], proc.Mp()), nil
    60  		} else {
    61  			return vector.NewConstFixed(resultType, 1, uvals[0], proc.Mp()), nil
    62  		}
    63  	}
    64  	return nil, moerr.NewInternalError(proc.Ctx, "the parameter is invalid")
    65  }
    66  
    67  func evaluateMemoryCapacityForDatabase(proc *process.Process, params ...interface{}) (int, error) {
    68  	return len(proc.SessionInfo.GetDatabase()), nil
    69  }
    70  
    71  func doDatabase(proc *process.Process, params ...interface{}) (interface{}, error) {
    72  	result := params[0].([]string)
    73  	result[0] = proc.SessionInfo.GetDatabase()
    74  	if len(result[0]) == 0 {
    75  		return nil, nil
    76  	}
    77  	return result, nil
    78  }
    79  
    80  // Database returns the default (current) database name
    81  func Database(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    82  	return adapter(vectors, proc, types.T_varchar.ToType(),
    83  		0,
    84  		evaluateMemoryCapacityForDatabase,
    85  		doDatabase)
    86  }
    87  
    88  func evaluateMemoryCapacityForUser(proc *process.Process, params ...interface{}) (int, error) {
    89  	return len(proc.SessionInfo.GetUserHost()), nil
    90  }
    91  
    92  func doUser(proc *process.Process, params ...interface{}) (interface{}, error) {
    93  	result := params[0].([]string)
    94  	result[0] = proc.SessionInfo.GetUserHost()
    95  	return result, nil
    96  }
    97  
    98  // User returns the user name and host name provided by the client
    99  func User(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   100  	return adapter(vectors, proc, types.T_varchar.ToType(),
   101  		0,
   102  		evaluateMemoryCapacityForUser,
   103  		doUser)
   104  }
   105  
   106  func evaluateMemoryCapacityForConnectionID(proc *process.Process, params ...interface{}) (int, error) {
   107  	return 8, nil
   108  }
   109  
   110  func doConnectionID(proc *process.Process, params ...interface{}) (interface{}, error) {
   111  	result := params[0].([]uint64)
   112  	result[0] = proc.SessionInfo.ConnectionID
   113  	return result, nil
   114  }
   115  
   116  // ConnectionID returns the connection ID (thread ID) for the connection
   117  func ConnectionID(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   118  	return adapter(vectors, proc, types.T_uint64.ToType(),
   119  		0,
   120  		evaluateMemoryCapacityForConnectionID,
   121  		doConnectionID)
   122  }
   123  
   124  func evaluateMemoryCapacityForCharset(proc *process.Process, params ...interface{}) (int, error) {
   125  	return len(proc.SessionInfo.GetCharset()), nil
   126  }
   127  
   128  func doCharset(proc *process.Process, params ...interface{}) (interface{}, error) {
   129  	result := params[0].([]string)
   130  	result[0] = proc.SessionInfo.GetCharset()
   131  	return result, nil
   132  }
   133  
   134  // Charset returns the character set of the argument
   135  func Charset(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   136  	//TODO: even the charset has one parameter but
   137  	//the result is utf8 always. So, we do not process the parameter
   138  	return adapter(vectors, proc, types.T_varchar.ToType(),
   139  		0,
   140  		evaluateMemoryCapacityForCharset,
   141  		doCharset)
   142  }
   143  
   144  func evaluateMemoryCapacityForCurrentRole(proc *process.Process, params ...interface{}) (int, error) {
   145  	return len(proc.SessionInfo.GetRole()), nil
   146  }
   147  
   148  func doCurrentRole(proc *process.Process, params ...interface{}) (interface{}, error) {
   149  	result := params[0].([]string)
   150  	role := proc.SessionInfo.GetRole()
   151  	if len(role) == 0 {
   152  		return nil, nil
   153  	}
   154  	result[0] = role
   155  	return result, nil
   156  }
   157  
   158  // Current_Role returns the current active roles
   159  func CurrentRole(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   160  	return adapter(vectors, proc, types.T_varchar.ToType(),
   161  		0,
   162  		evaluateMemoryCapacityForCurrentRole,
   163  		doCurrentRole)
   164  }
   165  
   166  func evaluateMemoryCapacityForFoundRows(proc *process.Process, params ...interface{}) (int, error) {
   167  	return 8, nil
   168  }
   169  
   170  func doFoundRows(proc *process.Process, params ...interface{}) (interface{}, error) {
   171  	result := params[0].([]uint64)
   172  	result[0] = 0
   173  	return result, nil
   174  }
   175  
   176  // For a SELECT with a LIMIT clause, the number of rows that would be returned were there no LIMIT clause
   177  func FoundRows(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   178  	return adapter(vectors, proc, types.T_uint64.ToType(),
   179  		0,
   180  		evaluateMemoryCapacityForFoundRows,
   181  		doFoundRows)
   182  }
   183  
   184  // ICU library version
   185  func ICULIBVersion(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   186  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   187  		func(proc *process.Process, params ...interface{}) (int, error) {
   188  			return 0, nil
   189  		},
   190  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   191  			result := params[0].([]string)
   192  			result[0] = ""
   193  			return result, nil
   194  		},
   195  	)
   196  }
   197  
   198  // Value of the AUTOINCREMENT column for the last INSERT
   199  func LastInsertID(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   200  	return adapter(vectors, proc, types.T_uint64.ToType(), 0,
   201  		func(proc *process.Process, params ...interface{}) (int, error) {
   202  			return 0, nil
   203  		},
   204  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   205  			result := params[0].([]uint64)
   206  			result[0] = proc.SessionInfo.LastInsertID
   207  			return result, nil
   208  		},
   209  	)
   210  }
   211  
   212  func LastQueryIDWithoutParam(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   213  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   214  		func(proc *process.Process, params ...interface{}) (int, error) {
   215  			return 0, nil
   216  		},
   217  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   218  			cnt := int64(len(proc.SessionInfo.QueryId))
   219  			if cnt == 0 {
   220  				return nil, nil
   221  			}
   222  			result := params[0].([]string)
   223  			// LAST_QUERY_ID(-1) returns the most recently-executed query (equivalent to LAST_QUERY_ID()).
   224  			idx, err := makeQueryIdIdx(-1, cnt, proc)
   225  			if err != nil {
   226  				return nil, err
   227  			}
   228  			result[0] = proc.SessionInfo.QueryId[idx]
   229  			return result, nil
   230  		},
   231  	)
   232  }
   233  
   234  func LastQueryID(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   235  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   236  		func(proc *process.Process, params ...interface{}) (int, error) {
   237  			return 0, nil
   238  		},
   239  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   240  			cnt := int64(len(proc.SessionInfo.QueryId))
   241  			if cnt == 0 {
   242  				return nil, nil
   243  			}
   244  			result := params[0].([]string)
   245  			loc := vector.MustTCols[int64](vectors[0])[0]
   246  			idx, err := makeQueryIdIdx(loc, cnt, proc)
   247  			if err != nil {
   248  				return nil, err
   249  			}
   250  			result[0] = proc.SessionInfo.QueryId[idx]
   251  			return result, nil
   252  		},
   253  	)
   254  }
   255  
   256  func makeQueryIdIdx(loc, cnt int64, proc *process.Process) (int, error) {
   257  	// https://docs.snowflake.com/en/sql-reference/functions/last_query_id.html
   258  	var idx int
   259  	if loc < 0 {
   260  		if loc < -cnt {
   261  			return 0, moerr.NewInvalidInput(proc.Ctx, "index out of range: %d", loc)
   262  		}
   263  		idx = int(loc + cnt)
   264  	} else {
   265  		if loc > cnt {
   266  			return 0, moerr.NewInvalidInput(proc.Ctx, "index out of range: %d", loc)
   267  		}
   268  		idx = int(loc)
   269  	}
   270  	return idx, nil
   271  }
   272  
   273  // RolesGraphml returns a GraphML document representing memory role subgraphs
   274  func RolesGraphml(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   275  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   276  		func(proc *process.Process, params ...interface{}) (int, error) {
   277  			return 0, nil
   278  		},
   279  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   280  			result := params[0].([]string)
   281  			result[0] = ""
   282  			return result, nil
   283  		},
   284  	)
   285  }
   286  
   287  // RowCount returns The number of rows updated
   288  func RowCount(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   289  	return adapter(vectors, proc, types.T_uint64.ToType(), 0,
   290  		func(proc *process.Process, params ...interface{}) (int, error) {
   291  			return 0, nil
   292  		},
   293  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   294  			result := params[0].([]uint64)
   295  			result[0] = 0
   296  			return result, nil
   297  		},
   298  	)
   299  }
   300  
   301  // Return a string that indicates the MySQL server version
   302  func Version(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   303  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   304  		func(proc *process.Process, params ...interface{}) (int, error) {
   305  			return len(proc.SessionInfo.GetVersion()), nil
   306  		},
   307  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   308  			result := params[0].([]string)
   309  			result[0] = proc.SessionInfo.GetVersion()
   310  			return result, nil
   311  		},
   312  	)
   313  }
   314  
   315  // Collation	returns the collation of the string argument
   316  func Collation(vectors []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   317  	return adapter(vectors, proc, types.T_varchar.ToType(), 0,
   318  		func(proc *process.Process, params ...interface{}) (int, error) {
   319  			return len(proc.SessionInfo.GetCollation()), nil
   320  		},
   321  		func(proc *process.Process, params ...interface{}) (interface{}, error) {
   322  			result := params[0].([]string)
   323  			result[0] = proc.SessionInfo.GetCollation()
   324  			return result, nil
   325  		},
   326  	)
   327  }