forked from huawei/openGauss-server
891 lines
33 KiB
C++
891 lines
33 KiB
C++
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* -------------------------------------------------------------------------
|
|
*
|
|
* jit_common.cpp
|
|
* Definitions used both by LLVM and TVM jitted code.
|
|
*
|
|
* IDENTIFICATION
|
|
* src/gausskernel/storage/mot/jit_exec/jit_common.cpp
|
|
*
|
|
* -------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*
|
|
* ATTENTION:
|
|
* 1. Be sure to include gscodegen.h before anything else to avoid clash with PM definition in datetime.h.
|
|
* 2. Be sure to include libintl.h before gscodegen.h to avoid problem with gettext.
|
|
*/
|
|
#include "libintl.h"
|
|
#include "codegen/gscodegen.h"
|
|
#include "postgres.h"
|
|
#include "catalog/pg_operator.h"
|
|
#include "global.h"
|
|
#include "jit_common.h"
|
|
#include "utilities.h"
|
|
#include "jit_plan.h"
|
|
#include "mm_global_api.h"
|
|
|
|
namespace JitExec {
|
|
DECLARE_LOGGER(JitCommon, JitExec)
|
|
|
|
extern JitCommandType ConvertCommandType(int pgCommandType, bool isPKey)
|
|
{
|
|
JitCommandType result = JIT_COMMAND_INVALID;
|
|
|
|
switch (pgCommandType) {
|
|
case CMD_INSERT:
|
|
result = JIT_COMMAND_INSERT;
|
|
break;
|
|
|
|
case CMD_UPDATE:
|
|
result = JIT_COMMAND_UPDATE;
|
|
break;
|
|
|
|
case CMD_DELETE:
|
|
result = JIT_COMMAND_DELETE;
|
|
break;
|
|
|
|
case CMD_SELECT:
|
|
result = JIT_COMMAND_SELECT;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((result == JIT_COMMAND_UPDATE) && !isPKey) {
|
|
result = JIT_COMMAND_RANGE_UPDATE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
extern const char* CommandToString(JitCommandType commandType)
|
|
{
|
|
switch (commandType) {
|
|
case JIT_COMMAND_INSERT:
|
|
return "Insert";
|
|
case JIT_COMMAND_UPDATE:
|
|
return "Point-Update";
|
|
case JIT_COMMAND_SELECT:
|
|
return "Point-Select";
|
|
case JIT_COMMAND_DELETE:
|
|
return "Point-Delete";
|
|
case JIT_COMMAND_RANGE_UPDATE:
|
|
return "Range-Update";
|
|
case JIT_COMMAND_RANGE_SELECT:
|
|
return "Range-Select";
|
|
case JIT_COMMAND_AGGREGATE_RANGE_SELECT:
|
|
return "Aggregate-Range-Select";
|
|
case JIT_COMMAND_POINT_JOIN:
|
|
return "Point-Join";
|
|
case JIT_COMMAND_RANGE_JOIN:
|
|
return "Range-Join";
|
|
case JIT_COMMAND_AGGREGATE_JOIN:
|
|
return "Aggregate-Range-Join";
|
|
case JIT_COMMAND_COMPOUND_SELECT:
|
|
return "Compound-Select";
|
|
|
|
case JIT_COMMAND_INVALID:
|
|
default:
|
|
return "Invalid command";
|
|
}
|
|
}
|
|
|
|
extern bool IsRangeCommand(JitCommandType commandType)
|
|
{
|
|
bool rangeCommand = false;
|
|
|
|
switch (commandType) {
|
|
case JIT_COMMAND_RANGE_UPDATE:
|
|
case JIT_COMMAND_RANGE_SELECT:
|
|
case JIT_COMMAND_AGGREGATE_RANGE_SELECT:
|
|
case JIT_COMMAND_POINT_JOIN:
|
|
case JIT_COMMAND_RANGE_JOIN:
|
|
case JIT_COMMAND_AGGREGATE_JOIN:
|
|
rangeCommand = true;
|
|
break;
|
|
|
|
default:
|
|
rangeCommand = false;
|
|
break;
|
|
}
|
|
|
|
return rangeCommand;
|
|
}
|
|
|
|
extern bool IsJoinCommand(JitCommandType commandType)
|
|
{
|
|
bool joinCommand = false;
|
|
|
|
switch (commandType) {
|
|
case JIT_COMMAND_POINT_JOIN:
|
|
case JIT_COMMAND_RANGE_JOIN:
|
|
case JIT_COMMAND_AGGREGATE_JOIN:
|
|
joinCommand = true;
|
|
break;
|
|
|
|
default:
|
|
joinCommand = false;
|
|
break;
|
|
}
|
|
|
|
return joinCommand;
|
|
}
|
|
|
|
extern MOT::Table* GetTableFromQuery(const Query* query)
|
|
{
|
|
// we reject queries that reference more than one table
|
|
if (list_length(query->rtable) != 1) {
|
|
MOT_LOG_TRACE("Cannot retrieve query table: query does not have exactly one rtable entry");
|
|
return NULL;
|
|
}
|
|
|
|
RangeTblEntry* rte = (RangeTblEntry*)linitial(query->rtable);
|
|
Oid relid = rte->relid;
|
|
MOT_LOG_TRACE("Seeing relid=%u relname=%s", (unsigned)rte->relid, rte->relname);
|
|
|
|
MOT::Table* table = MOT::GetTableManager()->GetTableByExternal(relid);
|
|
if (table != nullptr) {
|
|
MOT_LOG_DEBUG("Retrieved table %p by external id %u: %s", table, relid, table->GetLongTableName().c_str());
|
|
} else {
|
|
MOT_LOG_TRACE("Failed to find table by external relation id: %u", relid);
|
|
}
|
|
return table;
|
|
}
|
|
|
|
extern int MapTableColumnToIndex(MOT::Table* table, const MOT::Index* index, int columnId)
|
|
{
|
|
const int16_t* indexColumnIds = index->GetColumnKeyFields();
|
|
int keyColumnCount = index->GetNumFields();
|
|
for (int i = 0; i < keyColumnCount; ++i) {
|
|
if (indexColumnIds[i] == columnId) {
|
|
MOT_LOG_TRACE("Table %s column %d mapped to index %s column %d",
|
|
table->GetTableName().c_str(),
|
|
columnId,
|
|
index->GetName().c_str(),
|
|
i);
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
extern int BuildColumnMap(MOT::Table* table, MOT::Index* index, int** columnMap)
|
|
{
|
|
int tableColumnCount = (int)table->GetFieldCount();
|
|
*columnMap = (int*)MOT::MemSessionAlloc(((uint64_t)tableColumnCount) * sizeof(int));
|
|
if (*columnMap) {
|
|
for (int i = 0; i < tableColumnCount; ++i) {
|
|
int indexColumnId = MapTableColumnToIndex(table, index, i);
|
|
(*columnMap)[i] = indexColumnId;
|
|
}
|
|
} else {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compilation", "Failed to allocate column map of size %d", tableColumnCount);
|
|
tableColumnCount = -1;
|
|
}
|
|
return tableColumnCount;
|
|
}
|
|
|
|
extern int BuildIndexColumnOffsets(MOT::Table* table, const MOT::Index* index, int** offsets)
|
|
{
|
|
const uint16_t* keyLength = index->GetLengthKeyFields();
|
|
int indexColumnCount = index->GetNumFields();
|
|
*offsets = (int*)MOT::MemSessionAlloc(((uint64_t)indexColumnCount) * sizeof(int));
|
|
if (*offsets) {
|
|
int offset = 0;
|
|
for (int i = 0; i < indexColumnCount; ++i) {
|
|
MOT_LOG_TRACE("Setting index %s column %d offset to %d", index->GetName().c_str(), i, offset);
|
|
(*offsets)[i] = offset;
|
|
offset += keyLength[i];
|
|
}
|
|
} else {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compilation", "Failed to allocate index offset array of size %d", indexColumnCount);
|
|
indexColumnCount = -1;
|
|
}
|
|
return indexColumnCount;
|
|
}
|
|
|
|
extern bool IsTypeSupported(int resultType)
|
|
{
|
|
switch (resultType) {
|
|
case BOOLOID:
|
|
case CHAROID:
|
|
case INT1OID:
|
|
case INT2OID:
|
|
case INT4OID:
|
|
case INT8OID:
|
|
case TIMESTAMPOID:
|
|
case DATEOID:
|
|
case FLOAT4OID:
|
|
case FLOAT8OID:
|
|
case NUMERICOID:
|
|
case VARCHAROID:
|
|
case BPCHAROID:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
extern bool IsStringType(int type)
|
|
{
|
|
switch (type) {
|
|
case VARCHAROID:
|
|
case BPCHAROID:
|
|
case TEXTOID:
|
|
case BYTEAOID:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
extern bool IsPrimitiveType(int type)
|
|
{
|
|
switch (type) {
|
|
case BOOLOID:
|
|
case CHAROID:
|
|
case INT1OID:
|
|
case INT2OID:
|
|
case INT4OID:
|
|
case INT8OID:
|
|
case TIMEOID:
|
|
case TIMESTAMPOID:
|
|
case DATEOID:
|
|
case FLOAT4OID:
|
|
case FLOAT8OID:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static bool IsEqualsWhereOperator(int whereOp)
|
|
{
|
|
bool result = false;
|
|
|
|
if ((whereOp == BooleanEqualOperator) || (whereOp == CHAREQOID) || (whereOp == INT1EQOID) ||
|
|
(whereOp == INT2EQOID) || (whereOp == INT4EQOID) || (whereOp == INT8EQOID) || (whereOp == FLOAT4EQOID) ||
|
|
(whereOp == FLOAT8EQOID) || (whereOp == NUMERICEQOID) || (whereOp == TIMESTAMPEQOID) ||
|
|
(whereOp == DATEEQOID) || (whereOp == BPCHAREQOID) || (whereOp == TEXTEQOID)
|
|
|
|
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
|
|| (whereOp == INT24EQOID) || (whereOp == INT42EQOID) || (whereOp == INT84EQOID) || (whereOp == INT48EQOID) ||
|
|
(whereOp == INT82EQOID) || (whereOp == INT28EQOID) || (whereOp == FLOAT48EQOID) || (whereOp == FLOAT84EQOID) ||
|
|
(whereOp == 1108 /* time_eq */) || (whereOp == TIMETZEQOID) || (whereOp == 5550 /* smalldatetime_eq */) ||
|
|
(whereOp == 2347 /* date_eq_timestamp */) || (whereOp == 2373 /* timestamp_eq_date */) ||
|
|
(whereOp == 2360 /* date_eq_timestamptz */) || (whereOp == 2386 /* timestamptz_eq_date */) ||
|
|
(whereOp == 2536 /* timestamp_eq_timestamptz */) || (whereOp == 2542 /* timestamptz_eq_timestamp */) ||
|
|
(whereOp == INTERVALEQOID)
|
|
#endif
|
|
) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool IsLessThanWhereOperator(int whereOp)
|
|
{
|
|
bool result = false;
|
|
|
|
if ((whereOp == 631) /* charlt */ || (whereOp == 5515) /* int1lt */
|
|
|| (whereOp == INT2LTOID) || (whereOp == INT4LTOID) || (whereOp == INT8LTOID) || (whereOp == FLOAT4LTOID) ||
|
|
(whereOp == FLOAT8LTOID) || (whereOp == NUMERICLTOID) || (whereOp == TIMESTAMPLTOID) ||
|
|
(whereOp == DATELTOID) || (whereOp == BPCHARLTOID) || (whereOp == TEXTLTOID)
|
|
|
|
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
|
|| (whereOp == INT24LTOID) || (whereOp == INT42LTOID) || (whereOp == INT84LTOID) || (whereOp == INT48LTOID) ||
|
|
(whereOp == INT82LTOID) || (whereOp == INT28LTOID) || (whereOp == FLOAT48LTOID) || (whereOp == FLOAT84LTOID) ||
|
|
(whereOp == 1108 /* time_lt */) || (whereOp == 1552 /* timetz_lt */) ||
|
|
(whereOp == 5550 /* smalldatetime_lt */) || (whereOp == 2347 /* date_lt_timestamp */) ||
|
|
(whereOp == 2373 /* timestamp_lt_date */) || (whereOp == 2360 /* date_lt_timestamptz */) ||
|
|
(whereOp == 2386 /* timestamptz_lt_date */) || (whereOp == 2536 /* timestamp_lt_timestamptz */) ||
|
|
(whereOp == 2542 /* timestamptz_lt_timestamp */) || (whereOp == 1332 /* interval_lt */)
|
|
#endif
|
|
) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool IsGreaterThanWhereOperator(int whereOp)
|
|
{
|
|
bool result = false;
|
|
|
|
if ((whereOp == 633) /* chargt */ || (whereOp == 5517) /* int1lt */
|
|
|| (whereOp == INT2GTOID) || (whereOp == INT4GTOID) || (whereOp == INT8GTOID) || (whereOp == FLOAT4GTOID) ||
|
|
(whereOp == FLOAT8GTOID) || (whereOp == NUMERICGTOID) || (whereOp == TIMESTAMPGTOID) ||
|
|
(whereOp == DATEGTOID) || (whereOp == BPCHARGTOID) || (whereOp == TEXTGTOID)
|
|
|
|
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
|
|| (whereOp == INT24GTOID) || (whereOp == INT42GTOID) || (whereOp == INT84GTOID) || (whereOp == INT48GTOID) ||
|
|
(whereOp == INT82GTOID) || (whereOp == INT28GTOID) || (whereOp == FLOAT48GTOID) || (whereOp == FLOAT84GTOID) ||
|
|
(whereOp == 1112 /* time_gt */) || (whereOp == 1554 /* timetz_gt */) ||
|
|
(whereOp == 5554 /* smalldatetime_gt */) || (whereOp == 2349 /* date_gt_timestamp */) ||
|
|
(whereOp == 2375 /* timestamp_gt_date */) || (whereOp == 2362 /* date_gt_timestamptz */) ||
|
|
(whereOp == 2388 /* timestamptz_gt_date */) || (whereOp == 2538 /* timestamp_gt_timestamptz */) ||
|
|
(whereOp == 2544 /* timestamptz_gt_timestamp */) || (whereOp == 1334 /* interval_gt */)
|
|
#endif
|
|
) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool IsLessEqualsWhereOperator(int whereOp)
|
|
{
|
|
bool result = false;
|
|
|
|
if ((whereOp == 632) /* charle */ || (whereOp == 5516) /* int1le */
|
|
|| (whereOp == INT2LEOID) || (whereOp == INT4LEOID) || (whereOp == INT8LEOID) || (whereOp == FLOAT4LEOID) ||
|
|
(whereOp == FLOAT8LEOID) || (whereOp == NUMERICLEOID) || (whereOp == TIMESTAMPLEOID) ||
|
|
(whereOp == DATELEOID) || (whereOp == 1059 /* bpcharle */) || (whereOp == 665 /* text_le */)
|
|
|
|
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
|
|| (whereOp == INT24LEOID) || (whereOp == INT42LEOID) || (whereOp == INT84LEOID) || (whereOp == INT48LEOID) ||
|
|
(whereOp == INT82LEOID) || (whereOp == INT28LEOID) || (whereOp == FLOAT48LEOID) || (whereOp == FLOAT84LEOID) ||
|
|
(whereOp == 1111 /* time_le */) || (whereOp == 1553 /* timetz_le */) ||
|
|
(whereOp == 5553 /* smalldatetime_le */) || (whereOp == 2346 /* date_le_timestamp */) ||
|
|
(whereOp == 2372 /* timestamp_le_date */) || (whereOp == 2359 /* date_le_timestamptz */) ||
|
|
(whereOp == 2385 /* timestamptz_le_date */) || (whereOp == 2535 /* timestamp_le_timestamptz */) ||
|
|
(whereOp == 2541 /* timestamptz_le_timestamp */) || (whereOp == 1333 /* interval_le */)
|
|
#endif
|
|
) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool IsGreaterEqualsWhereOperator(int whereOp)
|
|
{
|
|
bool result = false;
|
|
|
|
if ((whereOp == 634) /* charge */ || (whereOp == 5518) /* int1ge */
|
|
|| (whereOp == INT2GEOID) || (whereOp == INT4GEOID) || (whereOp == INT8GEOID) || (whereOp == FLOAT4GEOID) ||
|
|
(whereOp == FLOAT8GEOID) || (whereOp == NUMERICGEOID) || (whereOp == TIMESTAMPGEOID) ||
|
|
(whereOp == DATEGEOID) || (whereOp == 1061 /* bpcharge */) || (whereOp == 667 /* text_ge */)
|
|
|
|
#ifdef MOT_JIT_ADVANCED_WHERE_OP
|
|
|| (whereOp == INT24GEOID) || (whereOp == INT42GEOID) || (whereOp == INT84GEOID) || (whereOp == INT48GEOID) ||
|
|
(whereOp == INT82GEOID) || (whereOp == INT28GEOID) || (whereOp == FLOAT48GEOID) || (whereOp == FLOAT84GEOID) ||
|
|
(whereOp == 1113 /* time_ge */) || (whereOp == 1555 /* timetz_ge */) ||
|
|
(whereOp == 5549 /* smalldatetime_ge */) || (whereOp == 2348 /* date_ge_timestamp */) ||
|
|
(whereOp == 2374 /* timestamp_ge_date */) || (whereOp == 2361 /* date_ge_timestamptz */) ||
|
|
(whereOp == 2387 /* timestamptz_ge_date */) || (whereOp == 2537 /* timestamp_ge_timestamptz */) ||
|
|
(whereOp == 2543 /* timestamptz_ge_timestamp */) || (whereOp == 1335 /* interval_ge */)
|
|
#endif
|
|
) {
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
extern bool IsWhereOperatorSupported(int whereOp)
|
|
{
|
|
return ClassifyWhereOperator(whereOp) != JIT_WOC_INVALID;
|
|
}
|
|
|
|
extern JitWhereOperatorClass ClassifyWhereOperator(int whereOp)
|
|
{
|
|
JitWhereOperatorClass result = JIT_WOC_INVALID;
|
|
|
|
if (IsEqualsWhereOperator(whereOp)) {
|
|
result = JIT_WOC_EQUALS;
|
|
} else if (IsLessThanWhereOperator(whereOp)) {
|
|
result = JIT_WOC_LESS_THAN;
|
|
} else if (IsGreaterThanWhereOperator(whereOp)) {
|
|
result = JIT_WOC_GREATER_THAN;
|
|
} else if (IsLessEqualsWhereOperator(whereOp)) {
|
|
result = JIT_WOC_LESS_EQUALS;
|
|
} else if (IsGreaterEqualsWhereOperator(whereOp)) {
|
|
result = JIT_WOC_GREATER_EQUALS;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
#define APPLY_UNARY_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
#define APPLY_BINARY_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
#define APPLY_TERNARY_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
#define APPLY_UNARY_CAST_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
#define APPLY_BINARY_CAST_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
#define APPLY_TERNARY_CAST_OPERATOR(funcId, name) \
|
|
case funcId: \
|
|
break;
|
|
|
|
extern bool IsFuncIdSupported(int funcId)
|
|
{
|
|
bool result = true;
|
|
switch (funcId) {
|
|
APPLY_OPERATORS()
|
|
default:
|
|
result = false;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#undef APPLY_UNARY_OPERATOR
|
|
#undef APPLY_BINARY_OPERATOR
|
|
#undef APPLY_TERNARY_OPERATOR
|
|
#undef APPLY_UNARY_CAST_OPERATOR
|
|
#undef APPLY_BINARY_CAST_OPERATOR
|
|
#undef APPLY_TERNARY_CAST_OPERATOR
|
|
|
|
extern bool IsFullPrefixSearch(const int* columnArray, int columnCount, int* firstZeroColumn)
|
|
{
|
|
*firstZeroColumn = -1;
|
|
for (int i = 0; i < columnCount; ++i) {
|
|
if (columnArray[i] == 0) {
|
|
if (*firstZeroColumn == -1) {
|
|
*firstZeroColumn = i;
|
|
}
|
|
} else if (*firstZeroColumn != -1) {
|
|
MOT_LOG_TRACE(
|
|
"Invalid where clause: non-full prefix encountered (intermediate zero column at %d)", *firstZeroColumn);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
extern JitQuerySortOrder GetQuerySortOrder(const Query* query)
|
|
{
|
|
JitQuerySortOrder result = JIT_QUERY_SORT_INVALID;
|
|
|
|
if (!query->sortClause) {
|
|
MOT_LOG_TRACE("Query has no sort clause, setting it by default to ascending");
|
|
result = JIT_QUERY_SORT_ASCENDING;
|
|
} else {
|
|
SortGroupClause* sgc = (SortGroupClause*)linitial(query->sortClause);
|
|
int op = (int)sgc->sortop;
|
|
MOT_LOG_TRACE("Checking sort order by operator %d", op);
|
|
if ((op == INT48LTOID) || (op == 58) /* boolean less than */ || (op == INT2LTOID) || (op == INT4LTOID) ||
|
|
(op == INT8LTOID) || (op == INT84LTOID) || (op == INT24LTOID) || (op == INT42LTOID) || (op == INT28LTOID) ||
|
|
(op == INT82LTOID) || (op == 5515) /* int1lt */ || (op == FLOAT4LTOID) || (op == FLOAT8LTOID) ||
|
|
(op == FLOAT48LTOID) || (op == FLOAT84LTOID) || (op == NUMERICLTOID) || (op == 631) /* char less than */ ||
|
|
(op == TEXTLTOID) || (op == BPCHARLTOID) || (op == 1957) /* bytealt */ || (op == DATELTOID) ||
|
|
(op == 1110) /* time_lt */ || (op == 1552) /* timetz_lt */ || (op == 1322) /* timestamptz_lt */ ||
|
|
(op == 1332) /* interval_lt */ || (op == TIMESTAMPLTOID) || (op == 5552) /* smalldatetime_lt */) {
|
|
MOT_LOG_TRACE("Found ascending sort order by sortop %d", op);
|
|
result = JIT_QUERY_SORT_ASCENDING;
|
|
} else if ((op == INT48GTOID) || (op == 59) /* boolgt */ || (op == INT2GTOID) || (op == INT4GTOID) ||
|
|
(op == INT8GTOID) || (op == INT84GTOID) || (op == INT24GTOID) || (op == INT42GTOID) ||
|
|
(op == INT28GTOID) || (op == INT82GTOID) || (op == 5517) /* int1gt */ || (op == FLOAT4GTOID) ||
|
|
(op == FLOAT8GTOID) || (op == FLOAT48GTOID) || (op == FLOAT84GTOID) || (op == NUMERICGTOID) ||
|
|
(op == 633) /* chargt */ || (op == TEXTGTOID) || (op == BPCHARGTOID) || (op == 1959) /* byteagt */ ||
|
|
(op == DATEGTOID) || (op == 1112) /* time_gt */ || (op == 1554) /* timetz_gt */ ||
|
|
(op == 1324) /* timestamptz_gt */ || (op == 1334) /* interval_gt */ || (op == TIMESTAMPGTOID) ||
|
|
(op == 5554) /* smalldatetime_gt */) {
|
|
MOT_LOG_TRACE("Found descending sort order by sortop %d", op);
|
|
result = JIT_QUERY_SORT_DESCENDING;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
extern int GetAggregateTupleColumnIdAndType(const Query* query, int& zeroType)
|
|
{
|
|
TargetEntry* targetEntry = (TargetEntry*)linitial(query->targetList);
|
|
int tupleColId = targetEntry->resno - 1;
|
|
Aggref* aggRef = (Aggref*)targetEntry->expr;
|
|
zeroType = (int)aggRef->aggtype;
|
|
|
|
return tupleColId;
|
|
}
|
|
|
|
/** @brief Initializes a table info struct. */
|
|
extern bool InitTableInfo(TableInfo* tableInfo, MOT::Table* table, MOT::Index* index)
|
|
{
|
|
tableInfo->m_table = table;
|
|
tableInfo->m_index = index;
|
|
|
|
tableInfo->m_tableColumnCount = BuildColumnMap(table, index, &tableInfo->m_columnMap);
|
|
if (tableInfo->m_columnMap == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate table column map for code-generation context");
|
|
return false;
|
|
}
|
|
tableInfo->m_indexColumnCount = BuildIndexColumnOffsets(table, index, &tableInfo->m_indexColumnOffsets);
|
|
if (tableInfo->m_indexColumnOffsets == nullptr) {
|
|
MOT::MemSessionFree(tableInfo->m_columnMap);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/** @brief Releases all resources associated with a table info struct. */
|
|
extern void DestroyTableInfo(TableInfo* tableInfo)
|
|
{
|
|
if (tableInfo != nullptr) {
|
|
if (tableInfo->m_columnMap != nullptr) {
|
|
MOT::MemSessionFree(tableInfo->m_columnMap);
|
|
}
|
|
if (tableInfo->m_indexColumnOffsets != nullptr) {
|
|
MOT::MemSessionFree(tableInfo->m_indexColumnOffsets);
|
|
}
|
|
}
|
|
}
|
|
|
|
extern bool PrepareSubQueryData(JitContext* jitContext, JitCompoundPlan* plan)
|
|
{
|
|
bool result = true;
|
|
|
|
// allocate sub-query data array
|
|
int subQueryCount = plan->_sub_query_count;
|
|
MOT_LOG_TRACE("Preparing %u sub-query data items", subQueryCount);
|
|
uint32_t allocSize = sizeof(JitContext::SubQueryData) * subQueryCount;
|
|
jitContext->m_subQueryData = (JitContext::SubQueryData*)MOT::MemGlobalAllocAligned(allocSize, L1_CACHE_LINE);
|
|
if (jitContext->m_subQueryData == nullptr) {
|
|
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
|
"Generate JIT code",
|
|
"Failed to allocate %u bytes for %d sub-query data items in JIT context object",
|
|
allocSize,
|
|
subQueryCount);
|
|
result = false;
|
|
} else {
|
|
// traverse all search expressions and for each sub-link expression prepare a sub-query data item
|
|
jitContext->m_subQueryCount = subQueryCount;
|
|
for (int i = 0; i < plan->_outer_query_plan->_query._search_exprs._count; ++i) {
|
|
if (plan->_outer_query_plan->_query._search_exprs._exprs[i]._expr->_expr_type == JIT_EXPR_TYPE_SUBLINK) {
|
|
// get sub-query index from sub-link expression
|
|
JitSubLinkExpr* subLinkExpr =
|
|
(JitSubLinkExpr*)plan->_outer_query_plan->_query._search_exprs._exprs[i]._expr;
|
|
int subQueryIndex = subLinkExpr->_sub_query_index;
|
|
MOT_ASSERT(subQueryIndex < subQueryCount);
|
|
MOT_LOG_TRACE("Preparing sub-query %u data", subQueryIndex);
|
|
JitContext::SubQueryData* subQueryData = &jitContext->m_subQueryData[subQueryIndex];
|
|
|
|
// nullify unknown members
|
|
subQueryData->m_tupleDesc = nullptr;
|
|
subQueryData->m_slot = nullptr;
|
|
subQueryData->m_searchKey = nullptr;
|
|
subQueryData->m_endIteratorKey = nullptr;
|
|
|
|
// prepare sub-query data items according to sub-plan type
|
|
JitPlan* subPlan = plan->_sub_query_plans[subQueryIndex];
|
|
JitPlanType subPlanType = subPlan->_plan_type;
|
|
MOT_ASSERT((subPlanType == JIT_PLAN_POINT_QUERY) || (subPlanType == JIT_PLAN_RANGE_SCAN));
|
|
|
|
if (subPlanType == JIT_PLAN_POINT_QUERY) { // simple point-select
|
|
MOT_ASSERT(((JitPointQueryPlan*)subPlan)->_command_type == JIT_COMMAND_SELECT);
|
|
JitPointQueryPlan* subPointQueryPlan = (JitPointQueryPlan*)subPlan;
|
|
if (subPointQueryPlan->_command_type == JIT_COMMAND_SELECT) {
|
|
MOT_LOG_TRACE("Detected point-query select sub-plan");
|
|
subQueryData->m_commandType = JIT_COMMAND_SELECT;
|
|
JitSelectPlan* selectPlan = (JitSelectPlan*)subPlan;
|
|
subQueryData->m_table = selectPlan->_query._table;
|
|
subQueryData->m_index = subQueryData->m_table->GetPrimaryIndex();
|
|
subQueryData->m_indexId = subQueryData->m_index->GetExtId();
|
|
MOT_LOG_TRACE("Installed sub-query %d index id: %" PRIu64, i, subQueryData->m_indexId);
|
|
} else {
|
|
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
|
"Generate JIT code",
|
|
"Invalid sub-point-query plan command type: %s",
|
|
CommandToString(subPointQueryPlan->_command_type));
|
|
result = false;
|
|
break;
|
|
}
|
|
} else if (subPlanType == JIT_PLAN_RANGE_SCAN) { // aggregate or "limit 1" range select
|
|
MOT_ASSERT(((JitRangeScanPlan*)subPlan)->_command_type == JIT_COMMAND_SELECT);
|
|
JitRangeScanPlan* subRangeScanPlan = (JitRangeScanPlan*)subPlan;
|
|
if (subRangeScanPlan->_command_type == JIT_COMMAND_SELECT) {
|
|
MOT_LOG_TRACE("Detected range-scan select sub-plan");
|
|
JitRangeSelectPlan* rangeSelectPlan = (JitRangeSelectPlan*)subPlan;
|
|
subQueryData->m_table = rangeSelectPlan->_index_scan._table;
|
|
subQueryData->m_index = subQueryData->m_table->GetIndex(rangeSelectPlan->_index_scan._index_id);
|
|
if (rangeSelectPlan->_aggregate._aggreaget_op != JIT_AGGREGATE_NONE) { // aggregate range-scan
|
|
subQueryData->m_commandType = JIT_COMMAND_AGGREGATE_RANGE_SELECT;
|
|
} else if (rangeSelectPlan->_limit_count == 1) {
|
|
subQueryData->m_commandType = JIT_COMMAND_RANGE_SELECT; // implies "limit 1" clause
|
|
} else {
|
|
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
|
"Generate JIT code",
|
|
"Invalid sub-query range-scan plan: neither aggregate nor \"limit 1\" clause found");
|
|
result = false;
|
|
break;
|
|
}
|
|
} else {
|
|
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL,
|
|
"Generate JIT code",
|
|
"Invalid sub-query range-scan plan command type: %s",
|
|
CommandToString(subRangeScanPlan->_command_type));
|
|
result = false;
|
|
break;
|
|
}
|
|
} else {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_INTERNAL, "Generate JIT code", "Invalid sub-query plan type: %d", (int)subPlanType);
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static bool CloneStringDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
bytea* value = DatumGetByteaP(source);
|
|
size_t len = VARSIZE(value); // includes header len VARHDRSZ
|
|
char* src = VARDATA(value);
|
|
|
|
// special case: empty string
|
|
if (len == 0) {
|
|
len = VARHDRSZ;
|
|
}
|
|
size_t strSize = len - VARHDRSZ;
|
|
MOT_LOG_TRACE("CloneStringDatum(): len = %u, src = %*.*s", (unsigned)len, strSize, strSize, src);
|
|
|
|
bytea* copy = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
copy = (bytea*)MOT::MemGlobalAlloc(len);
|
|
} else {
|
|
copy = (bytea*)MOT::MemSessionAlloc(len);
|
|
}
|
|
if (copy == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate %u bytes for datum string constant", (unsigned)len);
|
|
return false;
|
|
}
|
|
|
|
if (strSize > 0) {
|
|
errno_t erc = memcpy_s(VARDATA(copy), strSize, (uint8_t*)src, strSize);
|
|
securec_check(erc, "\0", "\0");
|
|
}
|
|
|
|
SET_VARSIZE(copy, len);
|
|
|
|
*target = PointerGetDatum(copy);
|
|
return true;
|
|
}
|
|
|
|
static bool CloneTimeTzDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
MOT::TimetzSt* value = (MOT::TimetzSt*)DatumGetPointer(source);
|
|
size_t allocSize = sizeof(MOT::TimetzSt);
|
|
MOT::TimetzSt* copy = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
copy = (MOT::TimetzSt*)MOT::MemGlobalAlloc(allocSize);
|
|
} else {
|
|
copy = (MOT::TimetzSt*)MOT::MemSessionAlloc(allocSize);
|
|
}
|
|
if (copy == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate %u bytes for datum TimeTZ constant", (unsigned)allocSize);
|
|
return false;
|
|
}
|
|
copy->m_time = value->m_time;
|
|
copy->m_zone = value->m_zone;
|
|
|
|
*target = PointerGetDatum(copy);
|
|
return true;
|
|
}
|
|
|
|
static bool CloneIntervalDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
MOT::IntervalSt* value = (MOT::IntervalSt*)DatumGetPointer(source);
|
|
size_t allocSize = sizeof(MOT::IntervalSt);
|
|
MOT::IntervalSt* copy = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
copy = (MOT::IntervalSt*)MOT::MemGlobalAlloc(allocSize);
|
|
} else {
|
|
copy = (MOT::IntervalSt*)MOT::MemSessionAlloc(allocSize);
|
|
}
|
|
if (copy == nullptr) {
|
|
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
|
"JIT Compile",
|
|
"Failed to allocate %u bytes for datum Interval constant",
|
|
(unsigned)allocSize);
|
|
return false;
|
|
}
|
|
copy->m_day = value->m_day;
|
|
copy->m_month = value->m_month;
|
|
copy->m_time = value->m_time;
|
|
|
|
*target = PointerGetDatum(copy);
|
|
return true;
|
|
}
|
|
|
|
static bool CloneTIntervalDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
MOT::TintervalSt* value = (MOT::TintervalSt*)DatumGetPointer(source);
|
|
size_t allocSize = sizeof(MOT::TintervalSt);
|
|
MOT::TintervalSt* copy = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
copy = (MOT::TintervalSt*)MOT::MemGlobalAlloc(allocSize);
|
|
} else {
|
|
copy = (MOT::TintervalSt*)MOT::MemSessionAlloc(allocSize);
|
|
}
|
|
if (copy == nullptr) {
|
|
MOT_REPORT_ERROR(MOT_ERROR_OOM,
|
|
"JIT Compile",
|
|
"Failed to allocate %u bytes for datum TInterval constant",
|
|
(unsigned)allocSize);
|
|
return false;
|
|
}
|
|
copy->m_status = value->m_status;
|
|
copy->m_data[0] = value->m_data[0];
|
|
copy->m_data[1] = value->m_data[1];
|
|
|
|
*target = PointerGetDatum(copy);
|
|
return true;
|
|
}
|
|
|
|
static bool CloneNumericDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
varlena* var = (varlena*)DatumGetPointer(source);
|
|
Size len = VARSIZE(var);
|
|
struct varlena* result = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
result = (varlena*)MOT::MemGlobalAlloc(len);
|
|
} else {
|
|
result = (varlena*)MOT::MemSessionAlloc(len);
|
|
}
|
|
if (result == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate %u bytes for datum Numeric constant", (unsigned)len);
|
|
return false;
|
|
}
|
|
|
|
errno_t rc = memcpy_s(result, len, var, len);
|
|
securec_check(rc, "\0", "\0");
|
|
|
|
*target = NumericGetDatum((Numeric)result);
|
|
return true;
|
|
}
|
|
|
|
static bool CloneCStringDatum(Datum source, Datum* target, JitContextUsage usage)
|
|
{
|
|
char* src = DatumGetCString(source);
|
|
size_t len = strlen(src) + 1; // includes terminating null
|
|
|
|
char* copy = nullptr;
|
|
if (usage == JIT_CONTEXT_GLOBAL) {
|
|
copy = (char*)MOT::MemGlobalAlloc(len);
|
|
} else {
|
|
copy = (char*)MOT::MemSessionAlloc(len);
|
|
}
|
|
if (copy == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate %u bytes for datum string constant", (unsigned)len);
|
|
return false;
|
|
}
|
|
|
|
errno_t erc = memcpy_s(copy, len, src, len);
|
|
securec_check(erc, "\0", "\0");
|
|
|
|
*target = PointerGetDatum(copy);
|
|
return true;
|
|
}
|
|
|
|
extern bool CloneDatum(Datum source, int type, Datum* target, JitContextUsage usage)
|
|
{
|
|
bool result = true;
|
|
if (IsStringType(type)) {
|
|
result = CloneStringDatum(source, target, usage);
|
|
} else {
|
|
switch (type) {
|
|
case TIMETZOID:
|
|
result = CloneTimeTzDatum(source, target, usage);
|
|
break;
|
|
|
|
case INTERVALOID:
|
|
result = CloneIntervalDatum(source, target, usage);
|
|
break;
|
|
|
|
case TINTERVALOID:
|
|
result = CloneTIntervalDatum(source, target, usage);
|
|
break;
|
|
|
|
case NUMERICOID:
|
|
result = CloneNumericDatum(source, target, usage);
|
|
break;
|
|
|
|
case UNKNOWNOID:
|
|
result = CloneCStringDatum(source, target, usage);
|
|
break;
|
|
|
|
default:
|
|
MOT_LOG_TRACE("Unsupported non-primitive constant type: %d", type);
|
|
result = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
extern bool PrepareDatumArray(Const* constArray, uint32_t constCount, JitDatumArray* datumArray)
|
|
{
|
|
size_t allocSize = sizeof(JitDatum) * constCount;
|
|
JitDatum* datums = (JitDatum*)MOT::MemGlobalAlloc(allocSize);
|
|
if (datums == nullptr) {
|
|
MOT_REPORT_ERROR(
|
|
MOT_ERROR_OOM, "JIT Compile", "Failed to allocate %u bytes for constant datum array", (unsigned)allocSize);
|
|
return false;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < constCount; ++i) {
|
|
Const* constValue = &constArray[i];
|
|
datums[i].m_isNull = constValue->constisnull;
|
|
datums[i].m_type = constValue->consttype;
|
|
if (!datums[i].m_isNull) {
|
|
if (IsPrimitiveType(constValue->constvalue)) {
|
|
datums[i].m_datum = constValue->constvalue;
|
|
} else {
|
|
if (!CloneDatum(
|
|
constValue->constvalue, constValue->consttype, &datums[i].m_datum, JIT_CONTEXT_GLOBAL)) {
|
|
MOT_LOG_TRACE("Failed to prepare datum value");
|
|
for (uint32_t j = 0; j < i; ++j) {
|
|
if (!datums[j].m_isNull && !IsPrimitiveType(datums[j].m_type)) {
|
|
MOT::MemGlobalFree(DatumGetPointer(datums[j].m_datum));
|
|
}
|
|
}
|
|
MOT::MemGlobalFree(datums);
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
datumArray->m_datumCount = constCount;
|
|
datumArray->m_datums = datums;
|
|
return true;
|
|
}
|
|
} // namespace JitExec
|