diff --git a/src/gausskernel/process/tcop/postgres.cpp b/src/gausskernel/process/tcop/postgres.cpp index 73d7459a8..e0854e147 100644 --- a/src/gausskernel/process/tcop/postgres.cpp +++ b/src/gausskernel/process/tcop/postgres.cpp @@ -251,6 +251,9 @@ static int errdetail_recovery_conflict(void); static bool IsTransactionExitStmt(Node* parsetree); static bool IsTransactionExitStmtList(List* parseTrees); static bool IsTransactionStmtList(List* parseTrees); +#ifdef ENABLE_MOT +static bool IsTransactionPrepareStmt(const Node* parsetree); +#endif static void drop_unnamed_stmt(void); static void SigHupHandler(SIGNAL_ARGS); static void ForceModifyInitialPwd(const char* query_string, List* parsetree_list); @@ -2420,6 +2423,12 @@ static void exec_simple_query(const char* query_string, MessageType messageType, errmsg("SubTransaction is not supported for memory table"))); } + if (IsTransactionPrepareStmt(parsetree) && (IsMOTEngineUsed() || IsMixedEngineUsed())) { + /* Explicit prepare transaction is not supported for memory table */ + ereport(ERROR, (errcode(ERRCODE_FDW_OPERATION_NOT_SUPPORTED), errmodule(MOD_MOT), + errmsg("Explicit prepare transaction is not supported for memory table"))); + } + /* check for MOT update of indexed field. Can check only the querytree head, no need for drill down */ if (!IsTransactionExitStmt(parsetree) && (querytree_list != NULL && CheckMotIndexedColumnUpdate((Query*)linitial(querytree_list)))) { @@ -4100,14 +4109,22 @@ static void exec_bind_message(StringInfo input_message) #ifdef ENABLE_MOT /* set transaction storage engine and check for cross transaction violation */ SetCurrentTransactionStorageEngine(psrc->storageEngineType); - if (!IsTransactionExitStmt(psrc->raw_parse_tree) && IsMixedEngineUsed()) + if (!IsTransactionExitStmt(psrc->raw_parse_tree) && IsMixedEngineUsed()) { ereport(ERROR, (errcode(ERRCODE_FDW_CROSS_STORAGE_ENGINE_TRANSACTION_NOT_SUPPORTED), errmodule(MOD_MOT), - errmsg("Cross storage engine transaction is not supported"))); + errmsg("Cross storage engine transaction is not supported"))); + } /* block MOT engine queries in sub-transactions */ - if (!IsTransactionExitStmt(psrc->raw_parse_tree) && IsMOTEngineUsedInParentTransaction() && IsMOTEngineUsed()) + if (!IsTransactionExitStmt(psrc->raw_parse_tree) && IsMOTEngineUsedInParentTransaction() && IsMOTEngineUsed()) { ereport(ERROR, (errcode(ERRCODE_FDW_OPERATION_NOT_SUPPORTED), errmodule(MOD_MOT), - errmsg("SubTransaction is not supported for memory table"))); + errmsg("SubTransaction is not supported for memory table"))); + } + + if (IsTransactionPrepareStmt(psrc->raw_parse_tree) && (IsMOTEngineUsed() || IsMixedEngineUsed())) { + /* Explicit prepare transaction is not supported for memory table */ + ereport(ERROR, (errcode(ERRCODE_FDW_OPERATION_NOT_SUPPORTED), errmodule(MOD_MOT), + errmsg("Explicit prepare transaction is not supported for memory table"))); + } /* * MOT JIT Execution: @@ -5360,6 +5377,19 @@ static bool IsTransactionStmtList(List* parseTrees) return false; } +#ifdef ENABLE_MOT +static bool IsTransactionPrepareStmt(const Node* parsetree) +{ + if (parsetree && IsA(parsetree, TransactionStmt)) { + TransactionStmt* stmt = (TransactionStmt*)parsetree; + if (stmt->kind == TRANS_STMT_PREPARE) { + return true; + } + } + return false; +} +#endif + /* Release any existing unnamed prepared statement */ static void drop_unnamed_stmt(void) { diff --git a/src/gausskernel/storage/access/transam/xact.cpp b/src/gausskernel/storage/access/transam/xact.cpp index 95126e379..1e3d09df3 100644 --- a/src/gausskernel/storage/access/transam/xact.cpp +++ b/src/gausskernel/storage/access/transam/xact.cpp @@ -7807,7 +7807,7 @@ bool IsPGEngineUsed() } /* - * Check if we are using PG storage engine in parent transaction. + * Check if we are using MOT storage engine in parent transaction. */ bool IsMOTEngineUsedInParentTransaction() { diff --git a/src/gausskernel/storage/mot/core/src/infra/config/config_manager.cpp b/src/gausskernel/storage/mot/core/src/infra/config/config_manager.cpp index 6a9829029..53cc22e9b 100644 --- a/src/gausskernel/storage/mot/core/src/infra/config/config_manager.cpp +++ b/src/gausskernel/storage/mot/core/src/infra/config/config_manager.cpp @@ -384,7 +384,7 @@ bool ConfigManager::ReloadConfig(bool ignoreErrors /* = true */) // print loaded configuration LogLevel logLevel = LogLevel::LL_TRACE; - GetLayeredConfigTree()->GetUserConfigValue("Log/cfg_startup_log_level", logLevel, false); + GetLayeredConfigTree()->GetUserConfigValue("Log.cfg_startup_log_level", logLevel, false); if (MOT_CHECK_LOG_LEVEL(logLevel)) { GetLayeredConfigTree()->Print(logLevel); } diff --git a/src/gausskernel/storage/mot/core/src/storage/column.cpp b/src/gausskernel/storage/mot/core/src/storage/column.cpp index e7586fb3f..dcdea66f2 100644 --- a/src/gausskernel/storage/mot/core/src/storage/column.cpp +++ b/src/gausskernel/storage/mot/core/src/storage/column.cpp @@ -127,6 +127,7 @@ Column::Column() securec_check(erc, "\0", "\0"); erc = memset_s(&(this->m_type), sizeof(this->m_type), 0, sizeof(this->m_type)); securec_check(erc, "\0", "\0"); + this->m_envelopeType = 0; } Column::~Column() diff --git a/src/gausskernel/storage/mot/core/src/storage/column.h b/src/gausskernel/storage/mot/core/src/storage/column.h index afa2dc442..69d9e0459 100644 --- a/src/gausskernel/storage/mot/core/src/storage/column.h +++ b/src/gausskernel/storage/mot/core/src/storage/column.h @@ -162,6 +162,9 @@ public: /** @var Column does not allow null values. */ bool m_isNotNull; + + /** @var Envelope column type. */ + unsigned int m_envelopeType; }; // derived column classes diff --git a/src/gausskernel/storage/mot/core/src/storage/table.cpp b/src/gausskernel/storage/mot/core/src/storage/table.cpp index 8e8b789cb..e40cddd24 100644 --- a/src/gausskernel/storage/mot/core/src/storage/table.cpp +++ b/src/gausskernel/storage/mot/core/src/storage/table.cpp @@ -652,7 +652,8 @@ bool Table::CreateMultipleRows(size_t numRows, Row* rows[]) return res; } -RC Table::AddColumn(const char* colName, uint64_t size, MOT_CATALOG_FIELD_TYPES type, bool isNotNull) +RC Table::AddColumn( + const char* colName, uint64_t size, MOT_CATALOG_FIELD_TYPES type, bool isNotNull, unsigned int envelopeType) { // validate input parameters if (!colName || type >= MOT_CATALOG_FIELD_TYPES::MOT_TYPE_UNKNOWN) @@ -695,6 +696,7 @@ RC Table::AddColumn(const char* colName, uint64_t size, MOT_CATALOG_FIELD_TYPES m_columns[m_fieldCnt]->m_id = m_fieldCnt; m_columns[m_fieldCnt]->m_offset = m_tupleSize; m_columns[m_fieldCnt]->m_isNotNull = isNotNull; + m_columns[m_fieldCnt]->m_envelopeType = envelopeType; m_columns[m_fieldCnt]->SetKeySize(); m_tupleSize += size; @@ -817,7 +819,8 @@ size_t Table::SerializeItemSize(Column* column) size_t ret = SerializableARR::SerializeSize(column->m_name) + SerializablePOD::SerializeSize(column->m_size) + SerializablePOD::SerializeSize(column->m_type) + - SerializablePOD::SerializeSize(column->m_isNotNull); + SerializablePOD::SerializeSize(column->m_isNotNull) + + SerializablePOD::SerializeSize(column->m_envelopeType); // required for MOT JIT return ret; } @@ -830,6 +833,7 @@ char* Table::SerializeItem(char* dataOut, Column* column) dataOut = SerializablePOD::Serialize(dataOut, column->m_size); dataOut = SerializablePOD::Serialize(dataOut, column->m_type); dataOut = SerializablePOD::Serialize(dataOut, column->m_isNotNull); + dataOut = SerializablePOD::Serialize(dataOut, column->m_envelopeType); // required for MOT JIT return dataOut; } @@ -839,6 +843,7 @@ char* Table::DeserializeMeta(char* dataIn, CommonColumnMeta& meta) dataIn = SerializablePOD::Deserialize(dataIn, meta.m_size); dataIn = SerializablePOD::Deserialize(dataIn, meta.m_type); dataIn = SerializablePOD::Deserialize(dataIn, meta.m_isNotNull); + dataIn = SerializablePOD::Deserialize(dataIn, meta.m_envelopeType); // required for MOT JIT return dataIn; } @@ -1110,7 +1115,7 @@ void Table::Deserialize(const char* in) CommonColumnMeta col; for (uint32_t i = 0; i < saveFieldCount; i++) { dataIn = DeserializeMeta(dataIn, col); - if (AddColumn(col.m_name, col.m_size, col.m_type, col.m_isNotNull) != RC_OK) { + if (AddColumn(col.m_name, col.m_size, col.m_type, col.m_isNotNull, col.m_envelopeType) != RC_OK) { MOT_LOG_ERROR("Table::deserialize - failed to add column %u", i); return; } diff --git a/src/gausskernel/storage/mot/core/src/storage/table.h b/src/gausskernel/storage/mot/core/src/storage/table.h index 8e7dae8cc..3986deb60 100644 --- a/src/gausskernel/storage/mot/core/src/storage/table.h +++ b/src/gausskernel/storage/mot/core/src/storage/table.h @@ -634,7 +634,8 @@ public: * @param type The type name of the column. * @return RC error code. */ - RC AddColumn(const char* col_name, uint64_t size, MOT_CATALOG_FIELD_TYPES type, bool isNotNull = false); + RC AddColumn(const char* col_name, uint64_t size, MOT_CATALOG_FIELD_TYPES type, bool isNotNull = false, + unsigned int envelopeType = 0); /** * @brief Modifies the size of a column. This may be required for supporting ALTER TABLE. @@ -952,6 +953,8 @@ public: MOT_CATALOG_FIELD_TYPES m_type; bool m_isNotNull; + + unsigned int m_envelopeType; // required for MOT JIT }; /** diff --git a/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.cpp b/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.cpp index 8a423779e..de176fab7 100644 --- a/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.cpp +++ b/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.cpp @@ -935,10 +935,10 @@ static void VarLenFieldType( } } -static MOT::RC TableFieldType(const ColumnDef* colDef, MOT::MOT_CATALOG_FIELD_TYPES& type, int16* typeLen, bool& isBlob) +static MOT::RC TableFieldType( + const ColumnDef* colDef, MOT::MOT_CATALOG_FIELD_TYPES& type, int16* typeLen, Oid& typoid, bool& isBlob) { MOT::RC res = MOT::RC_OK; - Oid typoid; Type tup; Form_pg_type typeDesc; int32_t colLen; @@ -1210,7 +1210,8 @@ void MOTAdaptor::AddTableColumns(MOT::Table* table, List *tableElts, bool& hasBl break; } - MOT::RC res = TableFieldType(colDef, colType, &typeLen, isBlob); + Oid typoid = InvalidOid; + MOT::RC res = TableFieldType(colDef, colType, &typeLen, typoid, isBlob); if (res != MOT::RC_OK) { delete table; table = nullptr; @@ -1264,7 +1265,8 @@ void MOTAdaptor::AddTableColumns(MOT::Table* table, List *tableElts, bool& hasBl } } } - res = table->AddColumn(colDef->colname, typeLen, colType, colDef->is_not_null); + + res = table->AddColumn(colDef->colname, typeLen, colType, colDef->is_not_null, typoid); if (res != MOT::RC_OK) { delete table; table = nullptr; @@ -1724,7 +1726,7 @@ void MOTAdaptor::CreateKeyBuffer(Relation rel, MOTFdwStateSt* festate, int start } DatumToMOTKey(col, - expr, + expr->resultType, val, desc->attrs[orgCols[i] - 1]->atttypid, buf + offset, @@ -1948,26 +1950,25 @@ void MOTAdaptor::DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* da } inline void MOTAdaptor::VarcharToMOTKey( - MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill) + MOT::Column* col, Oid datumType, Datum datum, Oid colType, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill) { - if (expr != nullptr) { // LLVM passes nullptr for expr parameter - bool noValue = false; - switch (expr->resultType) { - case BYTEAOID: - case TEXTOID: - case VARCHAROID: - case CLOBOID: - case BPCHAROID: - break; - default: - noValue = true; - errno_t erc = memset_s(data, len, 0x00, len); - securec_check(erc, "\0", "\0"); - break; - } - if (noValue) { - return; - } + bool noValue = false; + switch (datumType) { + case BYTEAOID: + case TEXTOID: + case VARCHAROID: + case CLOBOID: + case BPCHAROID: + break; + default: + noValue = true; + errno_t erc = memset_s(data, len, 0x00, len); + securec_check(erc, "\0", "\0"); + break; + } + + if (noValue) { + return; } bytea* txt = DatumGetByteaP(datum); @@ -1984,13 +1985,13 @@ inline void MOTAdaptor::VarcharToMOTKey( size -= 1; } else { // switch to equal - if (type == BPCHAROID) { + if (colType == BPCHAROID) { fill = 0x20; // space ' ' == 0x20 } else { fill = 0x00; } } - } else if (type == BPCHAROID) { // handle padding for blank-padded type + } else if (colType == BPCHAROID) { // handle padding for blank-padded type fill = 0x20; } col->PackKey(data, (uintptr_t)src, size, fill); @@ -2000,25 +2001,21 @@ inline void MOTAdaptor::VarcharToMOTKey( } } -inline void MOTAdaptor::FloatToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data) +inline void MOTAdaptor::FloatToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data) { - if (expr != nullptr) { // LLVM passes nullptr for expr parameter - if (expr->resultType == FLOAT8OID) { - MOT::DoubleConvT dc; - MOT::FloatConvT fc; - dc.m_r = (uint64_t)datum; - fc.m_v = (float)dc.m_v; - uint64_t u = (uint64_t)fc.m_r; - col->PackKey(data, u, col->m_size); - } else { - col->PackKey(data, datum, col->m_size); - } + if (datumType == FLOAT8OID) { + MOT::DoubleConvT dc; + MOT::FloatConvT fc; + dc.m_r = (uint64_t)datum; + fc.m_v = (float)dc.m_v; + uint64_t u = (uint64_t)fc.m_r; + col->PackKey(data, u, col->m_size); } else { col->PackKey(data, datum, col->m_size); } } -inline void MOTAdaptor::NumericToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data) +inline void MOTAdaptor::NumericToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data) { Numeric n = DatumGetNumeric(datum); char buf[DECIMAL_MAX_SIZE]; @@ -2027,83 +2024,71 @@ inline void MOTAdaptor::NumericToMOTKey(MOT::Column* col, ExprState* expr, Datum col->PackKey(data, (uintptr_t)d, DECIMAL_SIZE(d)); } -inline void MOTAdaptor::TimestampToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data) +inline void MOTAdaptor::TimestampToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data) { - if (expr != nullptr) { - if (expr->resultType == TIMESTAMPTZOID) { - Timestamp result = DatumGetTimestamp(DirectFunctionCall1(timestamptz_timestamp, datum)); - col->PackKey(data, result, col->m_size); - } else if (expr->resultType == DATEOID) { - Timestamp result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, datum)); - col->PackKey(data, result, col->m_size); - } else { - col->PackKey(data, datum, col->m_size); - } + if (datumType == TIMESTAMPTZOID) { + Timestamp result = DatumGetTimestamp(DirectFunctionCall1(timestamptz_timestamp, datum)); + col->PackKey(data, result, col->m_size); + } else if (datumType == DATEOID) { + Timestamp result = DatumGetTimestamp(DirectFunctionCall1(date_timestamp, datum)); + col->PackKey(data, result, col->m_size); } else { col->PackKey(data, datum, col->m_size); } } -inline void MOTAdaptor::TimestampTzToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data) +inline void MOTAdaptor::TimestampTzToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data) { - if (expr != nullptr) { - if (expr->resultType == TIMESTAMPOID) { - TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(timestamp_timestamptz, datum)); - col->PackKey(data, result, col->m_size); - } else if (expr->resultType == DATEOID) { - TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(date_timestamptz, datum)); - col->PackKey(data, result, col->m_size); - } else { - col->PackKey(data, datum, col->m_size); - } + if (datumType == TIMESTAMPOID) { + TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(timestamp_timestamptz, datum)); + col->PackKey(data, result, col->m_size); + } else if (datumType == DATEOID) { + TimestampTz result = DatumGetTimestampTz(DirectFunctionCall1(date_timestamptz, datum)); + col->PackKey(data, result, col->m_size); } else { col->PackKey(data, datum, col->m_size); } } -inline void MOTAdaptor::DateToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data) +inline void MOTAdaptor::DateToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data) { - if (expr != nullptr) { - if (expr->resultType == TIMESTAMPOID) { - DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamp_date, datum)); - col->PackKey(data, result, col->m_size); - } else if (expr->resultType == TIMESTAMPTZOID) { - DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamptz_date, datum)); - col->PackKey(data, result, col->m_size); - } else { - col->PackKey(data, datum, col->m_size); - } + if (datumType == TIMESTAMPOID) { + DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamp_date, datum)); + col->PackKey(data, result, col->m_size); + } else if (datumType == TIMESTAMPTZOID) { + DateADT result = DatumGetDateADT(DirectFunctionCall1(timestamptz_date, datum)); + col->PackKey(data, result, col->m_size); } else { col->PackKey(data, datum, col->m_size); } } void MOTAdaptor::DatumToMOTKey( - MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill) + MOT::Column* col, Oid datumType, Datum datum, Oid colType, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill) { EnsureSafeThreadAccessInline(); - switch (type) { + switch (colType) { case BYTEAOID: case TEXTOID: case VARCHAROID: case CLOBOID: case BPCHAROID: - VarcharToMOTKey(col, expr, datum, type, data, len, oper, fill); + VarcharToMOTKey(col, datumType, datum, colType, data, len, oper, fill); break; case FLOAT4OID: - FloatToMOTKey(col, expr, datum, data); + FloatToMOTKey(col, datumType, datum, data); break; case NUMERICOID: - NumericToMOTKey(col, expr, datum, data); + NumericToMOTKey(col, datumType, datum, data); break; case TIMESTAMPOID: - TimestampToMOTKey(col, expr, datum, data); + TimestampToMOTKey(col, datumType, datum, data); break; case TIMESTAMPTZOID: - TimestampTzToMOTKey(col, expr, datum, data); + TimestampTzToMOTKey(col, datumType, datum, data); break; case DATEOID: - DateToMOTKey(col, expr, datum, data); + DateToMOTKey(col, datumType, datum, data); break; default: col->PackKey(data, datum, col->m_size); diff --git a/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.h b/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.h index 85b6d8315..d52a93364 100644 --- a/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.h +++ b/src/gausskernel/storage/mot/fdw_adapter/src/mot_internal.h @@ -261,7 +261,7 @@ public: // data conversion static void DatumToMOT(MOT::Column* col, Datum datum, Oid type, uint8_t* data); - static void DatumToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, + static void DatumToMOTKey(MOT::Column* col, Oid datumType, Datum datum, Oid colType, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill = 0x00); static void MOTToDatum(MOT::Table* table, const Form_pg_attribute attr, uint8_t* data, Datum* value, bool* is_null); @@ -315,13 +315,13 @@ private: static void ValidateCreateIndex(IndexStmt* index, MOT::Table* table, MOT::TxnManager* txn); - static void VarcharToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, Oid type, uint8_t* data, size_t len, + static void VarcharToMOTKey(MOT::Column* col, Oid datumType, Datum datum, Oid colType, uint8_t* data, size_t len, KEY_OPER oper, uint8_t fill); - static void FloatToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data); - static void NumericToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data); - static void TimestampToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data); - static void TimestampTzToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data); - static void DateToMOTKey(MOT::Column* col, ExprState* expr, Datum datum, uint8_t* data); + static void FloatToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data); + static void NumericToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data); + static void TimestampToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data); + static void TimestampTzToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data); + static void DateToMOTKey(MOT::Column* col, Oid datumType, Datum datum, uint8_t* data); }; inline MOT::TxnManager* GetSafeTxn(const char* callerSrc, ::TransactionId txn_id = 0) diff --git a/src/gausskernel/storage/mot/jit_exec/src/jit_context.cpp b/src/gausskernel/storage/mot/jit_exec/src/jit_context.cpp index 0025adc33..f8238ee0a 100644 --- a/src/gausskernel/storage/mot/jit_exec/src/jit_context.cpp +++ b/src/gausskernel/storage/mot/jit_exec/src/jit_context.cpp @@ -612,6 +612,17 @@ static void CleanupJitContextPrimary(JitContext* jitContext) jitContext->m_index->DestroyKey(jitContext->m_endIteratorKey); jitContext->m_endIteratorKey = nullptr; } + + if (jitContext->m_beginIterator != nullptr) { + destroyIterator(jitContext->m_beginIterator); + jitContext->m_beginIterator = nullptr; + } + + if (jitContext->m_endIterator != nullptr) { + destroyIterator(jitContext->m_endIterator); + jitContext->m_endIterator = nullptr; + } + jitContext->m_index = nullptr; } @@ -636,6 +647,17 @@ static void CleanupJitContextInner(JitContext* jitContext) jitContext->m_innerIndex->DestroyKey(jitContext->m_innerEndIteratorKey); jitContext->m_innerEndIteratorKey = nullptr; } + + if (jitContext->m_innerBeginIterator != nullptr) { + destroyIterator(jitContext->m_innerBeginIterator); + jitContext->m_innerBeginIterator = nullptr; + } + + if (jitContext->m_innerEndIterator != nullptr) { + destroyIterator(jitContext->m_innerEndIterator); + jitContext->m_innerEndIterator = nullptr; + } + jitContext->m_innerIndex = nullptr; } } diff --git a/src/gausskernel/storage/mot/jit_exec/src/jit_helpers.cpp b/src/gausskernel/storage/mot/jit_exec/src/jit_helpers.cpp index 4abbb0179..fbf827a0e 100644 --- a/src/gausskernel/storage/mot/jit_exec/src/jit_helpers.cpp +++ b/src/gausskernel/storage/mot/jit_exec/src/jit_helpers.cpp @@ -449,9 +449,9 @@ void buildDatumKey( securec_check(erc, "\0", "\0"); } else { MOTAdaptor::DatumToMOTKey(column, - NULL, - value, (Oid)value_type, + value, + column->m_envelopeType, key->GetKeyBuf() + offset, column->m_size, KEY_OPER::READ_KEY_EXACT, diff --git a/src/gausskernel/storage/mot/jit_exec/src/jit_plan_expr.cpp b/src/gausskernel/storage/mot/jit_exec/src/jit_plan_expr.cpp index ed8bed6ad..5e555e9cf 100644 --- a/src/gausskernel/storage/mot/jit_exec/src/jit_plan_expr.cpp +++ b/src/gausskernel/storage/mot/jit_exec/src/jit_plan_expr.cpp @@ -156,7 +156,8 @@ void RangeScanExpressionCollector::EvaluateScanType() // first step: sort in-place all collected operators if (_index_op_count > 1) { - std::sort(&_index_ops[0], &_index_ops[_index_op_count - 1], IndexOpCmp); + MOT_LOG_TRACE("Sorting index ops") + std::stable_sort(&_index_ops[0], &_index_ops[_index_op_count], IndexOpCmp); } // now verify all but last two are equals operator @@ -227,7 +228,9 @@ bool RangeScanExpressionCollector::DetermineScanType(JitIndexScanType& scanType, void RangeScanExpressionCollector::Cleanup() { for (int i = 0; i < _index_op_count; ++i) { - freeExpr(_index_scan->_search_exprs._exprs[i]._expr); + if (_index_scan->_search_exprs._exprs[i]._expr != nullptr) { + freeExpr(_index_scan->_search_exprs._exprs[i]._expr); + } } _index_scan->_search_exprs._count = 0; _index_op_count = 0; @@ -255,23 +258,26 @@ int RangeScanExpressionCollector::RemoveSingleDuplicate() continue; } // now we need to decide which one to remove, - // our consideration is to keep equals operators and then join expressions + // our consideration is to keep first JOIN expressions and then EQUALS expressions int victim = -1; - if ((_index_ops[i]._op_class == JIT_WOC_EQUALS) || (_index_ops[j]._op_class == JIT_WOC_EQUALS)) { + if ((_index_ops[i]._op_class != JIT_WOC_EQUALS) || (_index_ops[j]._op_class != JIT_WOC_EQUALS)) { // we keep the equals operator for index scan, and leave the other as a filter - MOT_LOG_TRACE("RangeScanExpressionCollector(): Rejecting query due to duplicate index column " - "reference, one with EQUALS, one without"); + MOT_LOG_TRACE("RangeScanExpressionCollector(): Found duplicate index column reference, one with " + "EQUALS, one without - non-equals column will be considered as a filter"); if (_index_ops[i]._op_class != JIT_WOC_EQUALS) { victim = i; } else { victim = j; } + MOT_LOG_TRACE("Selected non-EQUALS victim at index %d", victim); } else if (_index_scan->_search_exprs._exprs[i]._join_expr && !_index_scan->_search_exprs._exprs[j]._join_expr) { victim = j; + MOT_LOG_TRACE("Selected non-JOIN victim at index %d", victim); } else if (!_index_scan->_search_exprs._exprs[i]._join_expr && _index_scan->_search_exprs._exprs[j]._join_expr) { victim = i; + MOT_LOG_TRACE("Selected non-JOIN victim at index %d", victim); } else if (_index_scan->_search_exprs._exprs[i]._join_expr && _index_scan->_search_exprs._exprs[j]._join_expr) { // both are join expressions, this is unacceptable, so we abort @@ -284,12 +290,18 @@ int RangeScanExpressionCollector::RemoveSingleDuplicate() // both items are not join expressions, both refer to index columns, so we arbitrarily drop one // of them victim = j; + MOT_LOG_TRACE("Selected arbitrary duplicate EQUALS victim at index %d", victim); } // switch victim with last item + MOT_LOG_TRACE( + "Removing victim index op at index %d and putting there index %d", victim, _index_op_count - 1); if (_index_scan->_search_exprs._exprs[victim]._expr != nullptr) { freeExpr(_index_scan->_search_exprs._exprs[victim]._expr); } + MOT_LOG_TRACE("Removing victim index op at index %d", victim); _index_scan->_search_exprs._exprs[victim] = _index_scan->_search_exprs._exprs[_index_op_count - 1]; + _index_scan->_search_exprs._exprs[_index_op_count - 1]._expr = nullptr; + _index_ops[victim] = _index_ops[_index_op_count - 1]; --_index_op_count; --_index_scan->_search_exprs._count; return 1; @@ -317,8 +329,15 @@ bool RangeScanExpressionCollector::IndexOpCmp(const IndexOpClass& lhs, const Ind int result = IntCmp(lhs._index_column_id, rhs._index_column_id); if (result == 0) { // make sure equals appears before other operators in case column id is equal - result = IntCmp(lhs._op_class, rhs._op_class); + if ((lhs._op_class == JIT_WOC_EQUALS) && (rhs._op_class != JIT_WOC_EQUALS)) { + result = -1; + } else if ((lhs._op_class != JIT_WOC_EQUALS) && (rhs._op_class == JIT_WOC_EQUALS)) { + result = 1; + } + // otherwise we keep order intact to avoid misinterpreting open range scan as inverted } + + // we return true when strict ascending order is preserved return result < 0; } @@ -336,6 +355,9 @@ bool RangeScanExpressionCollector::ScanHasHoles(JitIndexScanType scan_type) cons if (_index_ops[0]._index_column_id != 0) { MOT_LOG_TRACE( "RangeScanExpressionCollector(): Disqualifying query - Index scan does not begin with index column 0"); + for (int i = 0; i < _index_op_count; ++i) { + MOT_LOG_TRACE("Index column id %d: %d", i, _index_ops[i]._index_column_id); + } return true; }