blob: 881a2bc82d42975167f7f8e52883220c433e80be [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
**********************************************************************/
/* -*-C++-*- ***************************************************************
*
* File: ComSqlId.cpp
* Description:
*
* Created: 10/31/2006
* Language: C++
*
*
*****************************************************************************
*/
#include "ComSqlId.h"
#include "ExpError.h"
#include "str.h"
ComSqlId::ComSqlId(CollHeap * heap)
: heap_(heap)
{
}
Lng32 ComSqlId::createSqlSessionId
(char * sessionId, // INOUT
Lng32 maxSessionIdLen, // IN
Lng32 &actualSessionIdLen, // OUT
Lng32 nodeNumber, // IN
Lng32 cpu, // IN
Lng32 pin, // IN
Int64 processStartTS, // IN
Int64 sessionUniqueNum, // IN
Lng32 userNameLen, // IN
const char *userName, // IN
Lng32 userSessionNameLen, // IN
const char *userSessionName // IN
)
{
// if input buffer space is less then the needed space,
// return error.
if (maxSessionIdLen < MAX_SESSION_ID_LEN)
return -CLI_INVALID_ATTR_VALUE;
// The format of current session id is:
// MXID<version><segment><cpu><pin><processStartTS><sessNum><unLen><userName><snLen><sessionName>
str_sprintf
(sessionId, "%s%02d%03d%06d%018ld%010d%02d%s%02d%s",
COM_SESSION_ID_PREFIX,
SQ_SQL_ID_VERSION,
nodeNumber, // 3 digits
pin, // 6 digits
processStartTS, // 18 digits
(Lng32)sessionUniqueNum, // 10 digits
userNameLen, // 2 digits
userName, //
userSessionNameLen, // 2 digits
userSessionName
);
actualSessionIdLen = (Lng32)strlen(sessionId);
return 0;
}
Lng32 ComSqlId::createSqlQueryId
(char * queryId, // INOUT
Lng32 maxQueryIdLen, // IN
Lng32 &actualQueryIdLen, // OUT
Lng32 sessionIdLen, // IN
char * sessionId, // IN
Int64 queryUniqueNum, // IN
Lng32 queryNameLen, // IN
char * queryName // IN
)
{
// if input buffer space is less then the needed space,
// return error.
if (maxQueryIdLen < MAX_QUERY_ID_LEN)
return -CLI_INVALID_ATTR_VALUE;
// The format of current query id is:
// <session_id>_<unique_number>_<identifier_or_handle>
// <unique_number> is max 18 digits. Stored value is the actual
// number of digits delimited by underscores.
// Ex, queryNum of 12 will be store as _12_
//
str_sprintf(queryId, "%s_%ld_",
sessionId,
queryUniqueNum
);
Int32 queryIdLen = (Int32)strlen(queryId);
// check queryName length
if(queryNameLen > maxQueryIdLen - queryIdLen -1)
queryNameLen = maxQueryIdLen - queryIdLen -1;
// copy queryName to queryId
strncpy(&queryId[queryIdLen],queryName, queryNameLen);
actualQueryIdLen = queryIdLen + queryNameLen;
queryId[actualQueryIdLen] =0;
return 0;
}
Lng32 ComSqlId::getSqlIdAttr
(Lng32 attr, // which attr (SqlQueryIDAttr)
const char * queryId,// query ID
Lng32 queryIdLen, // query ID len
Int64 &value, // If returned attr is numeric,
// this field contains the returned value.
// If attr is of string type, this value is:
// on input,the max length of the buffer pointed to by stringValue
// on output, the actual length of the string attribute
char * stringValue) // null terminated string returned here
{
Lng32 retcode = 0;
Int64 version = str_atoi(&queryId[VERSION_OFFSET], VERSION_LEN);
switch (attr)
{
case SQLQUERYID_VERSION:
value = version;
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
break;
case SQLQUERYID_SEGMENTNUM:
{
// on SQ, the SEGMENT_NUM and CPUNUM is the same field - 3 digits
if (version == NEO_SQL_ID_VERSION)
value = str_atoi(&queryId[SEGMENT_OFFSET], NEO_SEGMENT_LEN);
else
value = str_atoi(&queryId[SEGMENT_OFFSET], SEGMENT_LEN);
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_SEGMENTNAME:
{
// not implemented yet
if(stringValue && value)
stringValue[0] = 0;
}
break;
case SQLQUERYID_CPUNUM:
{
// on SQ, the SEGMENT_NUM and CPUNUM is the same field - 3 digits
if (version == NEO_SQL_ID_VERSION)
value = str_atoi(&queryId[NEO_CPU_OFFSET], NEO_CPU_LEN);
else
value = str_atoi(&queryId[CPU_OFFSET], CPU_LEN);
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_PIN:
{
if (version == NEO_SQL_ID_VERSION)
value = str_atoi(&queryId[NEO_PIN_OFFSET], NEO_PIN_LEN);
else
value = str_atoi(&queryId[PIN_OFFSET], PIN_LEN);
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_EXESTARTTIME:
{
value = str_atoi(&queryId[STARTTS_OFFSET], STARTTS_LEN);
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_SESSIONNUM:
{
value = str_atoi(&queryId[SESSIONNUM_OFFSET], SESSIONNUM_LEN);
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_USERNAME:
{
Lng32 userNameLen =
(Lng32)str_atoi(&queryId[USERNAMELEN_OFFSET], USERNAMELEN_LEN);
if (userNameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
if (stringValue && value > userNameLen)
{
strncpy(stringValue, &queryId[USERNAME_OFFSET], userNameLen);
stringValue[userNameLen] = 0;
}
else
retcode = -CLI_INVALID_ATTR_VALUE ;
value = userNameLen;
}
break;
case SQLQUERYID_SESSIONNAME:
{
Lng32 userNameLen =
(Lng32)str_atoi(&queryId[USERNAMELEN_OFFSET], USERNAMELEN_LEN);
if (userNameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
Lng32 sessionNameLenOffset =
USERNAMELEN_OFFSET + USERNAMELEN_LEN + userNameLen;
Lng32 sessionNameLen =
(Lng32)str_atoi(&queryId[sessionNameLenOffset], SESSIONNAMELEN_LEN);
if (sessionNameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
if (stringValue && value > sessionNameLen )
{
strncpy(stringValue,
&queryId[sessionNameLenOffset+SESSIONNAMELEN_LEN],
sessionNameLen);
stringValue[sessionNameLen] = 0;
}
else
retcode = -CLI_INVALID_ATTR_VALUE;
value = sessionNameLen;
}
break;
case SQLQUERYID_SESSIONID:
{
// session Id = qid from start thru SessionName
// set current offset to userNameLen
Int32 currOffset = USERNAMELEN_OFFSET;
// get userNameLen
Int32 nameLen = (Int32)str_atoi(&queryId[currOffset], USERNAMELEN_LEN);
// go past Username
currOffset += USERNAMELEN_LEN + nameLen;
// get sessionName length
nameLen = (Int32)str_atoi(&queryId[currOffset], SESSIONNAMELEN_LEN);
if (nameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
// go past sessionName
currOffset += SESSIONNAMELEN_LEN + nameLen;
// check value for length
if(stringValue && value > currOffset)
{
// copy sessionId to stringValue
strncpy(stringValue, queryId, currOffset);
stringValue[currOffset]=0;
}
else
retcode = -CLI_INVALID_ATTR_VALUE;
value = currOffset;
}
break;
case SQLQUERYID_QUERYNUM:
{
Lng32 currOffset = USERNAMELEN_OFFSET;
Lng32 nameLen =
(Lng32)str_atoi(&queryId[currOffset], USERNAMELEN_LEN);
if (nameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
// skip user name
currOffset += USERNAMELEN_LEN + nameLen;
// skip session name
nameLen =
(Lng32)str_atoi(&queryId[currOffset], SESSIONNAMELEN_LEN);
if (nameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
currOffset += SESSIONNAMELEN_LEN + nameLen;
if (currOffset >= queryIdLen)
return -CLI_INVALID_ATTR_VALUE;
if (queryId[currOffset] != '_')
return -CLI_INVALID_ATTR_VALUE;
// skip "_" separator
currOffset += 1;
// find the next occurance of "_"
char * us = str_chr(&queryId[currOffset], '_');
if (us == NULL)
return -CLI_INVALID_ATTR_VALUE;
if ((currOffset + (us - (char *)(&queryId[currOffset]))) >= queryIdLen)
return -CLI_INVALID_ATTR_VALUE;
value = str_atoi(&queryId[currOffset],
us - (char *)(&queryId[currOffset]));
if (value < 0)
return -CLI_INVALID_ATTR_VALUE;
}
break;
case SQLQUERYID_STMTNAME:
{
Lng32 currOffset = USERNAMELEN_OFFSET;
Lng32 nameLen =
(Lng32)str_atoi(&queryId[currOffset], USERNAMELEN_LEN);
if (nameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
// skip user name
currOffset += USERNAMELEN_LEN + nameLen;
// skip session name
nameLen =
(Lng32)str_atoi(&queryId[currOffset], SESSIONNAMELEN_LEN);
if (nameLen < 0)
return -CLI_INVALID_ATTR_VALUE;
currOffset += SESSIONNAMELEN_LEN + nameLen;
if (currOffset >= queryIdLen)
return -CLI_INVALID_ATTR_VALUE;
if (queryId[currOffset] != '_')
return -CLI_INVALID_ATTR_VALUE;
// skip "_" separator
currOffset += 1;
// find the next occurance of "_"
char * us = str_chr(&queryId[currOffset], '_');
if (us == NULL)
return -CLI_INVALID_ATTR_VALUE;
// skip queryNum
currOffset += us - (char *)(&queryId[currOffset]);
if (currOffset >= queryIdLen)
return -CLI_INVALID_ATTR_VALUE;
// skip "_" separator
currOffset += 1;
//get statementName length as remaining string except trailing blanks
while (queryIdLen && queryId[queryIdLen-1] == ' ')
queryIdLen--;
Int32 qidStatementNameLen = queryIdLen - currOffset;
// check for enough space in StringValue
if(stringValue && value > qidStatementNameLen )
{
// copy and null terminate
strncpy(stringValue, &queryId[currOffset], qidStatementNameLen);
stringValue[qidStatementNameLen] = 0;
}
else
retcode = -CLI_INVALID_ATTR_VALUE;
value = qidStatementNameLen;
}
break;
default:
{
retcode = -CLI_INVALID_ATTR_NAME;
}
}
return retcode;
}
Lng32 ComSqlId::getSqlQueryIdAttr
(Lng32 attr, // which attr (SqlQueryIDAttr)
char * queryId, // query ID
Lng32 queryIdLen, // query ID len
Int64 &value, // If returned attr is of string type, this value is the
// max length of the buffer pointed to by stringValue.
// If returned attr is numeric, this field contains
// the returned value.
char * stringValue) // null terminated returned value for string attrs.
{
Lng32 retcode = 0;
if ((queryId == NULL) ||
(queryIdLen < MIN_QUERY_ID_LEN) ||
(strncmp(queryId, COM_SESSION_ID_PREFIX,
strlen(COM_SESSION_ID_PREFIX)) != 0))
return -CLI_INVALID_ATTR_VALUE;
retcode = getSqlIdAttr(attr, queryId, queryIdLen, value, stringValue);
return retcode;
}
Lng32 ComSqlId::getSqlSessionIdAttr
(Lng32 attr, // which attr (SqlQueryIDAttr)
char * queryId, // query ID
Lng32 queryIdLen, // query ID len
Int64 &value, // If returned attr is of string type, this value is the
// max length of the buffer pointed to by stringValue.
// If returned attr is numeric, this field contains
// the returned value.
char * stringValue) // null terminated returned value for string attrs.
{
Lng32 retcode = 0;
if ((queryId == NULL) ||
(queryIdLen < MIN_SESSION_ID_LEN) ||
(strncmp(queryId, COM_SESSION_ID_PREFIX,
strlen(COM_SESSION_ID_PREFIX)) != 0))
return -CLI_INVALID_ATTR_VALUE;
retcode = getSqlIdAttr(attr, queryId, queryIdLen, value, stringValue);
return retcode;
}
Lng32 ComSqlId::extractSqlSessionIdAttrs
(const char * sessionId, // IN
Lng32 maxSessionIdLen, // IN
Int64 &segmentNumber, // OUT
Int64 &cpu, // OUT
Int64 &pin, // OUT
Int64 &processStartTS, // OUT
Int64 &sessionUniqueNum, // OUT
Lng32 &userNameLen, // OUT
char * userName, // OUT
Lng32 &userSessionNameLen, // OUT
char * userSessionName, // OUT
Lng32 *version
)
{
Lng32 retcode = 0;
Int64 lc_version;
if ((sessionId == NULL) ||
((maxSessionIdLen > 0) && (maxSessionIdLen < MIN_SESSION_ID_LEN)) ||
(strncmp(sessionId, COM_SESSION_ID_PREFIX,
strlen(COM_SESSION_ID_PREFIX)) != 0))
return -1;
retcode = getSqlIdAttr(SQLQUERYID_SEGMENTNUM, sessionId,
maxSessionIdLen, segmentNumber, NULL);
if (retcode)
return retcode;
retcode = getSqlIdAttr(SQLQUERYID_CPUNUM, sessionId,
maxSessionIdLen, cpu, NULL);
if (retcode)
return retcode;
retcode = getSqlIdAttr(SQLQUERYID_PIN, sessionId,
maxSessionIdLen, pin, NULL);
if (retcode)
return retcode;
retcode = getSqlIdAttr(SQLQUERYID_EXESTARTTIME, sessionId,
maxSessionIdLen, processStartTS, NULL);
if (retcode)
return retcode;
retcode = getSqlIdAttr(SQLQUERYID_SESSIONNUM, sessionId,
maxSessionIdLen, sessionUniqueNum, NULL);
if (retcode)
return retcode;
if (userName)
{
// TBD
return -1;
}
if (userSessionName)
{
// TBD
return -1;
}
if (version != NULL)
{
retcode = getSqlIdAttr(SQLQUERYID_VERSION, sessionId,
maxSessionIdLen, lc_version, NULL);
if (retcode)
return retcode;
*version = (Lng32)lc_version;
}
return 0;
}
/*
DP2 Query Id Format:
Each of the part is in binary numeric format.
<segment><cpu><pin><processStartTS><queryNum>
<segment> : 1 byte
<cpu> : 1 byte
<pin> : 2 bytes(short)
<processStartTS> : 8 bytes (Int64)
<queryNum> : 4 bytes (Lng32)
*/
Lng32 ComSqlId::getDp2QueryIdString
(char * queryId, // IN
Lng32 queryIdLen, // IN
char * dp2QueryId, // INOUT
Lng32 &dp2QueryIdLen // OUT
)
{
if ((!queryId) ||
(queryIdLen < MAX_DP2_QUERY_ID_LEN))
return -1;
Int64 value;
Lng32 currOffset = 0;
// In case of Linux and NT, segment num and cpu num are same
// Copy them as short
// get cpu
getSqlQueryIdAttr(SQLQUERYID_CPUNUM, queryId, queryIdLen,
value, NULL);
*(short*)&dp2QueryId[currOffset] = (short)value;
currOffset += sizeof(short);
// get pin
getSqlQueryIdAttr(SQLQUERYID_PIN, queryId, queryIdLen,
value, NULL);
*(short*)&dp2QueryId[currOffset] = (short)value;
currOffset += sizeof(short);
// get process start time
getSqlQueryIdAttr(SQLQUERYID_EXESTARTTIME, queryId, queryIdLen,
value, NULL);
str_cpy_all(&dp2QueryId[currOffset], (char*)&value, sizeof(Int64));
currOffset += sizeof(Int64);
// get query num
getSqlQueryIdAttr(SQLQUERYID_QUERYNUM, queryId, queryIdLen,
value, NULL);
Lng32 qNum = (Lng32)value;
str_cpy_all(&dp2QueryId[currOffset], (char*)&qNum, sizeof(Lng32));
currOffset += sizeof(Lng32);
dp2QueryIdLen = currOffset;
return 0;
}
Lng32 ComSqlId::decomposeDp2QueryIdString
(char * queryId, // input: buffer containing dp2 query id
Lng32 queryIdLen, // input: length of query id
Lng32 *queryNum, // output: unique query number
Lng32 *segment, // output: segment number of master exe
Lng32 *cpu, // output: cpu number
Lng32 *pin, // output: pin
Int64 *timestamp // output: master exe process
// start time
)
{
if ((!queryId) ||
(queryIdLen < MAX_DP2_QUERY_ID_LEN))
return -1;
Lng32 currOffset = 0;
*segment = *(short*)&queryId[currOffset];
*cpu = *segment;
currOffset += sizeof(short);
*pin = *(short*)&queryId[currOffset];
currOffset += sizeof(short);
str_cpy_all((char*)timestamp, &queryId[currOffset], sizeof(Int64));
currOffset += sizeof(Int64);
str_cpy_all((char*)queryNum, &queryId[currOffset], sizeof(Lng32));
currOffset += sizeof(Lng32);
return 0;
}