Skip to content
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

Fix row::move_as behavior breaking reusability #1145

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Krzmbrzl
Copy link
Contributor

For the time being, this is merely a sketch of how I think the fix has to work. The current implementation fails at the unavailability of a session object at the row scope...

Once this is finished, this PR fixes #1144

src/core/row.cpp Outdated
Comment on lines 123 to 124
// Re-initialize blob object so it can be used in further queries
baseVal.initialize(session);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vadz any idea how I could access a session object in this place? I need one as it is the only object that can create blob backend objects, which is required to get a fully functioning blob again.

An alternative I have considered is to write a clone() or duplicate() function for the blob_backend interface that can be used here (via some interface from the blob object) but that seems rather inconsistent with how things work for all other backend objects. Besides, that would essentially require duplicating the functionality of session::make_blob_backend() and code duplication is never a good thing...

Yet another alternative I was thinking of was to keep track of moved-from objects at the row level in order to re-initialize them only when the object is actually used again, but I don't think there currently exists a (nice) way of executing code before new data is bound to the row's holders (as they are simply referenced as into holders in the respective statement.

I'd appreciate thoughts from your side on this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would require storing a back-pointer (or reference) to the session in each row object. It should probably be possible, but I wonder if we can avoid moving out of the blob here to avoid having to do this. Could you please remind me why was it necessary to add move_as() in the first place?

Copy link
Contributor Author

@Krzmbrzl Krzmbrzl Apr 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because blob objects are not copyable, which the standard get API requires

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but couldn't we just provide access to their data instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would require copying data into some sort of buffer (plus getting the type conversion magic in SOCI's internals right), which might not be what the user wants. Just imagine the scenario in which I want to fetch a blob just to write it into a different table. That'd then require copying the data into my temp buffer just to yet again copy the data into a new blob object that I can then use in my insertion query.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the simplest would be to add blob_impl::clone().

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for the writable blob received from the select after insert ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for the writable blob received from the select after insert ?

Sorry, I can't quite follow - there seems to be a verb missing in your sentence (that's important for your meaning) 👀

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible for the writable blob received from the select after insert ?

Sorry, I can't quite follow - there seems to be a verb missing in your sentence (that's important for your meaning) 👀

Sorry, I mean blob_impl::clone. Is it possible to clone the blob? Who will own the blob locator ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloning is not a good idea, I think. We don't want to duplicate the stored data. But we can create a new, empty blob from an existing one.

@vadz vadz added this to the 4.1.0 milestone Apr 26, 2024
@Krzmbrzl
Copy link
Contributor Author

Krzmbrzl commented May 1, 2024

@avpalienko could you debug where the SegFault for Oracle is coming from? You seem to have good access to an Oracle installation, whereas for me it is always super tedious to get something to work.

@avpalienko
Copy link

@avpalienko could you debug where the SegFault for Oracle is coming from? You seem to have good access to an Oracle installation, whereas for me it is always super tedious to get something to work.

I've debugged on windows and have no segfault. But test fails:


BLOB
Blob binding
move_as

D:\CMA\Dev\SOCI\soci_githab\tests\common-tests.h(6784)
...............................................................................

D:\CMA\Dev\SOCI\soci_githab\tests\common-tests.h(6784): FAILED:
{Unknown expression after the reported line}
due to unexpected exception with message:
soci error: Invalid handle while fetching data from "select b from soci_test
where id=:id" with :1=42.

===============================================================================
test cases: 2 | 1 passed | 1 failed
assertions: 162 | 161 passed | 1 failed

I think it's a result of the move_as. Lob locator binds to the statement in define_by_pos():

bbe->reset();
ociData_ = bbe->get_lob_locator();

and then it initialized by OCIDefineByPos(). But in row::move_as() we call dtor ~oracle_blob_backend() with OCIDescriptorFree inside. On the next fetch in the post_fetch we call bbe->set_lob_locator(). Inside it we set locator in the old released value and call OCILobIsOpen which returns OCI_INVALID_HANDLE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Using row::move_as while iterating rowset yields segmentation fault
3 participants