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

Transaction with custom sql exec not updating results #1091

Closed
rednazkela opened this issue Nov 10, 2021 · 5 comments
Closed

Transaction with custom sql exec not updating results #1091

rednazkela opened this issue Nov 10, 2021 · 5 comments

Comments

@rednazkela
Copy link

Context:
I'm using JSON fields on MySQL 8 though a custom function that allows me to handle all changes on MySQL instead of retrieving whole object to PHP, modify it and store it again, that must be the basic approach of propelorm on this data type.

I've created a custom setXXX method that takes the data to be modified and a Connection Interface as parameters to acomplish this but things gets weird at this point.

I'm testing the use cases for this with PHPUnit doing the following:

  1. Create an object with a JSON field set to empty json
    $obj = new \TableName();
    $obj->setXXX('{}'): // Using setter method provided by PropelORM
    $obj->save($con);

all asserts pass at this point

  1. Modify JSON field with custom method
    $obj->setXXXJSON('{"action":"set", "prop":"val"}', $con);

    1. This method internally call the MySQL function that creates a SQL stament that resolves that given instruction and returns it as string stored at $stmt
    2. Then that code is executed using $con->exec($stmt)
  2. Save method is not used because there's any change to the proper object but it needs to be refreshed to get the new JSON Field Value
    $obj = TableNameQuery::create()->findOneById($obj->getId());

at this point equality assert fails because
$obj->getXXX():
Expected: {"prop":"val"}
Actual: "{}"
At this point you may say... well your custom function didn't affect the database
BUT looking at MySQL table directly the actual value of JSON Field is {"prop":"val"}

Issue:
This means that 2. Modify JSON field with custom method actually happend but i cannot get that value back even though its stored at the database and instead I get the previous unmodified version of it

I've tried to create a new object
$other = \TableNameQuery::create()->findOneById($obj->getId());
But it shows the same field without been affected
$other->getXXX():
Expected: {"prop":"val"}
Actual: "{}"

While writing this I realized that I can change this from fuction to procedure to be executed internally by MySQL without the need to return the statement string to PHP to do that.
Also I'll try to create a new accesor method using custom sql to get this particular field to see if I'm able to see the change.

Thanks!

@DavidGoodwin
Copy link

tried turning instance pooling off?

@rednazkela
Copy link
Author

tried turning instance pooling off?

Just tried with this:
Propel::disableInstancePooling();
and I see no difference.

I made a custom accesor getXXXJSON($con) and it succesfully see those changes using
$sql = 'Select field from tablename where id = :id';
$id = $this->getIdnentest();
$stmt = $connection->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();

@mentalstring
Copy link

mentalstring commented Nov 10, 2021

My bet was also on instance pooling. Maybe activate query logging on mysql (SET global general_log = 1) to see if your "reload" query actually hits the server?

Or, since the title speaks of transactions, another idea is if your custom mysql function hasn't yet committed the changes in a way that the connection session of the reload sees them.

@rednazkela
Copy link
Author

@DavidGoodwin @mentalstring
I finally made it, disabling instance pooling was winning shot I just put it in the wrong place.
Finally, I ended up wrapping just the reload of the object in disable/enable pooling to keep all benefits of it in the rest of the code an its working fine.

Propel::disableInstancePooling();
$obj = TableNameQuery::create()->findOneById($obj->getId());
Propel::enableInstancePooling();

Thank you very much.

P.D. Do you know a way to handle DML senteces with JSON capabilities through PropelORM?

@DavidGoodwin
Copy link

P.D. Do you know a way to handle DML senteces with JSON capabilities through PropelORM?

No; sorry; beyond my pay grade ;-) (not something I've had to think about / use)

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

No branches or pull requests

3 participants