-
-
Notifications
You must be signed in to change notification settings - Fork 233
Fix for #8082 by making engine to use user buffers directly #8145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
At this point the testcase for #8082 produces exactly expected output. |
Modified testcase that also check coercion of input data. |
#8185 is already fixed in different ways in master and v5. I see no relation of #8189 with this PR. I actually see no relation of this PR with actual problem of #8082. In reality, I do not understand what is this PR about. |
Sorry, "reference to cursor" meant here. And Delphi applications are not affected more than others. My fault. |
…ate message buffer
Additionally failed QA tests:
|
Could someone review this, please? |
Updated, ready to merge. |
I wonder why these Android runners are so unstable. |
messages[i] = message; | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How many messages do you expect inside the statement? The csb_rpt
array may easily contain a hundred of elements, while only a couple of them may have messages, do I get it right? Isn't it an overkill to store the whole lot of useless nullptr
's inside the messages
array?
src/dsql/DsqlCompilerScratch.h
Outdated
@@ -70,6 +73,7 @@ class DsqlCompilerScratch : public BlrDebugWriter | |||
static const unsigned FLAG_DDL = 0x2000; | |||
static const unsigned FLAG_FETCH = 0x4000; | |||
static const unsigned FLAG_VIEW_WITH_CHECK = 0x8000; | |||
static const unsigned FLAG_EXEC_BLOCK = 0x100000; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was it intended to be 0x10000
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, most likely.
src/dsql/DsqlCursor.cpp
Outdated
m_keyBuffer(nullptr), | ||
m_keyBufferLength(0), | ||
m_message(req->getDsqlStatement()->getReceiveMsg()->msg_number), | ||
m_messageLength(0), | ||
m_resultSet(NULL), m_flags(flags), | ||
m_space(req->getPool(), SCRATCH), | ||
m_state(BOS), m_eof(false), m_position(0), m_cachedCount(0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please move all trivial initializations (priorly existing and your new ones) to the class declaration in the header file.
src/dsql/DsqlCursor.cpp
Outdated
{ | ||
delete[] m_keyBuffer; | ||
m_keyBuffer = nullptr; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unnecessary if
-- it's safe to call delete on null pointers per C++ standard.
m_messageLength = msg->getFormat(req)->fmt_length; | ||
// Save record key unconditionally because setCursorName() can be called after openCursor() | ||
m_keyBufferLength = req->req_rpb.getCount() * sizeof(RecordKey); | ||
m_keyBuffer = new RecordKey[req->req_rpb.getCount()]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and below (for buffer
): why unpooled new
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DsqlCursor
has no obvious pool and m_keyBuffer
(and buffer
below) is destructed explicitly, not via pool, so it doesn't rally matter what pool to use AFAIU. Default is not worse than any other.
{ | ||
TraceSQLStatementImpl stmt(dsqlRequest, NULL); | ||
TraceManager::event_dsql_free(att, &stmt, DSQL_drop); | ||
fb_assert(false); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just silently swallow the exception and then finalize the cleanup? AFAIU, this differs from the original code which could throw. Why is this difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because throwing in destructor is a very bad idea. Calling code can be unprepared for this. It is emergency case that should never happen so it is better to swallow the exception (in release build only) and let resources be finalized by pool.
src/dsql/DsqlRequests.cpp
Outdated
UCHAR* msgBuffer = req_msg_buffers[message->msg_buffer_number]; | ||
fb_assert(inMsg != nullptr); | ||
|
||
ULONG inMsgLength = dsqlStatement->getStatement()->getMessage(message->msg_number)->getFormat(request)->fmt_length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ULONG inMsgLength
src/dsql/DsqlRequests.cpp
Outdated
// In either case, there's more than one record. | ||
MessageNode* msg = dsqlStatement->getStatement()->getMessage(message->msg_number); | ||
// outMetadata can be nullptr. If not - it is already converted to message above | ||
ULONG outMsgLength = msg->getFormat(request)->fmt_length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const ULONG outMsgLength
src/dsql/StmtNodes.cpp
Outdated
UCHAR* MessageNode::getBuffer(Request* request) const | ||
{ | ||
MessageBuffer* buffer = request->getImpure<MessageBuffer>(impureOffset); | ||
if (buffer->buffer == nullptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better naming, please. buffer->buffer
reads terribly. I'd suggest something like MessageBuffer::data
instead.
src/dsql/StmtNodes.cpp
Outdated
MessageBuffer* buffer = request->getImpure<MessageBuffer>(impureOffset); | ||
if (buffer->buffer == nullptr) | ||
{ | ||
size_t length = buffer->format == nullptr ? format->fmt_length : buffer->format->fmt_length; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t length = buffer->format == nullptr ? format->fmt_length : buffer->format->fmt_length; | |
const ULONG length = buffer->format == nullptr ? format->fmt_length : buffer->format->fmt_length; |
Plan "A" is simple: