Bug #27852 NdbTransaction->execute returns 0 for read by key of unexisting records
Submitted: 16 Apr 2007 13:22 Modified: 27 Apr 2007 15:16
Reporter: Anatoly Pidruchny (Candidate Quality Contributor) Email Updates:
Status: Closed
Category:Server: Docs Severity:S3 (Non-critical)
Version:5.1.17 OS:Any
Assigned to: Jon Stephens Target Version:
Triage: D4 (Minor)

[16 Apr 2007 13:22] Anatoly Pidruchny
Description:
I started to have a problem with simple read by key operations after upgrading to 5.1.17.
I used 5.1.15 before the upgrade and I did not try if 5.1.16 has this problem. The problem
is that for these read by key operations NdbTransaction->execute returns 0 even when a
record does not exist. It is expected to return -1 in this case and it worked fine before
the upgrade.

How to repeat:
Please see the attached test program. It creates an empty table "garage" and tries to
read a record from it without populating first. NdbTransaction->execute returns 0 and the
program thinks that a valid existing record has been returned.
[16 Apr 2007 13:24] Anatoly Pidruchny
Test program

Attachment: no_record_not_found.cpp (application/octet-stream, text), 6.98 KiB.

[16 Apr 2007 13:39] Jonas Oreland
Hi,

We made a non-compatible change of AbortOption handling in 5.1.16
  http://dev.mysql.com/doc/refman/5.1/en/news-5-1-16.html

Let know if docs (html + api comments/docs) is sufficient

/Jonas
[16 Apr 2007 14:07] Anatoly Pidruchny
Hi, Jonas,

I read about the incompatible change: AbortOption enum became a member of NdbOperation
and default value of abortOption parameter of NdbTransaction::execute became
NdbOperation::DefaultAbortOption. But the problem is with the return value of 
NdbTransaction::execute. It is not clear when it is supposed to return -1 and when it is
supposed to return 0. This is what documentation says:

Return Value.   0 on success, -1 on failure. The fact that the transaction did not abort
does not necessarily mean that each operation was successful; you must check each
operation individually for errors.

Well, what is failure in this case? I expect that failure means that any of the
operations failed during execution, does not matter if the transaction was aborted or no.
Is it changed in 5.1.16? Does execute() return -1 now only when the transaction was
aborted? But then still there is a bug here. In the test program, I tried to change the
call to NdbTransaction::execute to:

myTrans->execute(NdbTransaction::NoCommit, NdbOperation::AbortOnError)

or

myTrans->execute(NdbTransaction::Commit, NdbOperation::AbortOnError)

These changes did not make any difference! It still returned 0 for an unexisting record.

Regards,

Anatoly.
[16 Apr 2007 15:03] Hartmut Holzgraefe
Starting with 5.1.16 NdbTransaction::execute() will no longer fail (i.e. return -1) on
NoDataFound errors, it will succeed and return 0 instead, but its error
information will still be set to reflect the actual error code and the NoDataFound
category.

So to test for NoDataFound situations you now have to check

  transaction->getNdbError().classification == NdbError:NoDataFound

even if execute() returned 0 for success
[16 Apr 2007 16:07] Anatoly Pidruchny
Hi, Hartmut,

sorry, why this special case is done only for the read operation? You said that
NdbTransaction::execute() will no longer fail (i.e. return -1) on NoDataFound errors.
Well, this is true for the read operation, but not true for other operations, such as
update or delete. My testing shows that NdbTransaction::execute() still returns -1 when I
try to update or delete an unexisting record. I still think that this change is not
justified and NdbTransaction::execute() should continue to return -1 on NoDataFound error
for all operations, including a read operation.

Regards,

Anatoly.
[17 Apr 2007 0:40] Jon Stephens
I'm removing myself (and Stefan) from this bug, and setting its status back to Open.

Please review and determine whether this change is intentional/desirable.

If so, then I'll update the docs.

Otherwise, assign the bug to be fixed (and then I'll document the fix).

Thanks.
[17 Apr 2007 5:58] Jonas Oreland
Anatoly,

NdbTransaction::execute will return -1 if and only if transaction has been
  aborted.

This change was made as there in the old semantics, was possible to construct
  a case where API had no knowledge to wheater transaction was aborted or
  not.

---

In your example program, you use a CommittedRead, 
and this currently can't abort a transaction.

---

Let me know if this clarifies situation.

/Jonas

ps.
i read the docs, and it looks ok.
however the entry in the changelog is a bit missleading...
and i'll get docs to update this...
ds.
[17 Apr 2007 6:03] Jonas Oreland
hmm...maybe docs could also be clarified a bit...
[17 Apr 2007 23:20] Jon Stephens
Jonas,

Thanks for the confirmation, I'll take it from here.
[18 Apr 2007 22:36] Jon Stephens
Thank you for your bug report. This issue has been addressed in the documentation. The
updated documentation will appear on our website shortly, and will be included in the
next release of the relevant products.
[27 Apr 2007 15:16] Anatoly Pidruchny
Hi, Jonas and Jon,

I read the updated documentation. I have one comment. Jonas said "In your example
program, you use a CommittedRead, and this currently can't abort a transaction." The
documentation does not specifically explain that the transaction may not abort even when
abortOption parameter is set to NdbOperation::AbortOnError. Could you please add some
explanation for this? Please take a look at these two pages:
http://dev.mysql.com/doc/ndbapi/en/class-ndbtransaction-execute.html
http://dev.mysql.com/doc/ndbapi/en/class-ndboperation-abortoption.html

There is no information that there are operations, such as LM_CommittedRead, for example,
that can not abort a transaction even when NdbOperation::AbortOnError option is used.
Well, there is a phrase "The fact that the transaction did not abort does not necessarily
mean that each operation was successful", but one may think that this can only happen when
NdbOperation::AO_IgnoreOnError option is used.

Thanks,

Anatoly.