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 Impact on me:
None 
Category:MySQL Server: Documentation Severity:S3 (Non-critical)
Version:5.1.17 OS:Any
Assigned to: Jon Stephens CPU Architecture:Any

[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.