Nested Sql queries function effect PHP Transaction? - php

I am going to write a long sql transaction and thinking to write reusable sql function so my question is that can i write the transaction in this fashion?
try {
// First of all, let's begin a transaction
$db->beginTransaction();
// A set of queries; if one fails, an exception should be thrown
$db->query('first query');
UpdateEmp();
//anothre sql query function, i put him in another function so that i
//can use it seperately
$db->query('second query');
UpdateProject();
$db->query('third query');
// If we arrive here, it means that no exception was thrown
// i.e. no query has failed, and we can commit the transaction
$db->commit();
} catch (Exception $e) {
// An exception has been thrown
// We must rollback the transaction
$db->rollback();
}
whereas other sql functions will be like
function UpdateEmp(){
//separate sql queries for emplyee update
UpdateEmpProject();//nested sql query function
//Do any db error will stop and rollback the trasaction?
}
function UpdateEmpProject(){
//sepeate sql queries for emplyee update
}
My question is that, will the transaction rollback if any error occurred in UpdateEmp function? Suppose UpdateEmp() also contain another function with sql query, then the nested query will also effect the transaction result?

Related

How does MySQL transaction works and When to rollback?

i wonder how does transaction work.
Question is do I need to rollback if any error/exception occurs, where the Exception will be thrown and never reach the commit() call? If so why and how? and what rollback does exactly?
consider the followings PHP code (some Java code does similar things like so):
public function deleteAll():void{
$stmt = $this->con->prepare(
'DELETE FROM dd WHERE 1'
);
$this->con->begin_transaction();
if(!$stmt->execute()){
throw new Exception($stmt->error);
}
$this->con->commit();
}
public function insert(array $list):void{
$stmt = $this->con->prepare(
'INSERT INTO dd(cc) VALUES(?)'
);
$stmt->bind_param('s', $v);
$this->con->begin_transaction();
foreach($list as $v){
if(!$stmt->execute()){
throw new Exception($stmt->error);
}
}
$this->con->commit();
}
Note:
$this->con is the mysqli connection object (not using PDO, although different but PDO and mysqli will do similar thing like above).
database is MySQL, table using InnoDB engine.
Some people code shows they catch the Exception and do rollback. But I did not since the commit() is never executed if Exception is thrown. Then this let me wonder why does it need to rollback at all.
My assumption is if there are multiple queries to perform at once like the following:
public function replaceAllWith(array $list):void{
$this->con->begin_transaction();
try{
//do both previous queries at once
$this->deleteAll();
$this->insert($list);
$this->con->commit();
}catch(Exception $e){
//error
$this->con->rollback();
}
}
but then it still cannot rollback because each method/function is done and committed by different method and different transaction.
Second Question: Do I do each transaction in each method call, or only invoke transaction in the 'boss/parent' function which only call and coordinate 'subordinate/helper' functions to do work?
Not sure if I'm asking the right questions.
Database Transaction is confusing, many online resources show only the procedural process (commit only or then immediately rollback which make no differences to normal direct query) without OO concepts involved. Please any pros guide and give some advice. tq.

PDO - Catch if any of these queries returns an empty result

I am using Medoo (a PHP DB framework using PDO) with PDO::ERRMODE_EXCEPTION enabled. I have some queries in a try and catch block and I want to throw an exception if any of those queries return an empty result.
PS: $database->get() is a simple PDO SELECT returning a single row. I don't think it's relevant and I think my example applies also to PDO without frameworks.
try {
$q1 = $database->get(..);
$q2 = $database->get(..);
$q3 = $database->get(..);
$q4 = $database->get(..);
} catch (PDOException $e) {
die ("There was an error in a query.");
}
Right now I get into the catch block only if there is an error in the query, like I try to select a table that doesn't exist. I want to find the optimal way to avoid checking if every single query doesn't return an empty result manually, like I don't want to do this:
if (!$q1) { echo "No result"; }
if (!$q2) { echo "No result"; }
...
Is there a more generic approach?
Your logic is wrong, an Exception is an event that occurs during program execution that disrupts normal flow.
Query that returns an empty result set is not disrupting normal flow of your program, because that query executed successfully.
If you think that it's a good idea to use exceptions in order to signal that an empty result is returned, you have to throw that exception.
Eloquent, which is an ORM used by Laravel contains a method called firstOrFail and findOrFail which perform what you're after.
Your option is to either create such a method for Medoo or use a proper ORM such as Doctrine or Eloquent that can help you achieve such behavior out of the box.

ActiveCollab Custom Insert/Update query issue

I tried to execute some custom queries using DB::execute() function by passing query as a parameter to this function - update query on existing table. Before running this query I checked the connection object like this $connection = DB::getConnection(); and it returned a connection identifier. Then while executing query it returned bool true from execute function, though changes were not there in database table fields. Also if I pass query with wrong syntax, it is giving error.
Is there any rollback process going on in background with update query statement in ActiveCollab? If yes how to stop this rollback to avoid the changes done by my update query ?
Could anyone tell me what could be the issue here ?
All uncommitted transactions are automatically rolled back on script shutdown so you need to make sure that you are committing transactions that you opened:
try {
DB::beginWork();
// Do something
DB::commit();
} catch(Exception $e) {
DB::rollback();
throw $e;
}
or:
DB::transact(function() {
// Do something
});
If you are within a nested transaction and outer transactions gets rolled back, your updates will be rolled back as well.

MYSQL Autocommit when using multiple functions

Will try to make this as simple as possible. I'm using throw/catch with my functions. The function takes in a name a description, and an array of users. It adds the name and description to one table, then takes the array of users, and does a seperate function for adding them into a connector table. I set the function up to turn autocommit off until the last user is entered and then commit. The problem is that if one of the users fails to go in (due to a foreign key constraint), the transaction isn't backed out. Does the fact that I'm calling a seperate function "reset" the autocommit and cause it to not work as intended? Am I doing it wrong by putting the rollback in the Catch clause?
try
{
autocommit=0
run insert query
if query fails: throw error, rollback
else
for count of array
run another function (this function does more SQL and throws its own errors if it fails)
autocommit=1
}
catch
{
rollback, autocommit=1;
display error
}
Hopefully I haven't oversimplified the code. Any help would be appreciated.
$this->dbh->beginTransaction();
try {
// do stuff
$this->dbh->commit();
} catch (PDOException $e) {
$this->dbh->rollBack();
throw $e;
}

beginTransaction() and commit() for prepared and nonprepared statements

I have following code:
try{
$db->beginTransaction();
$handler = $db->prepare(...);
$handler->execute()
$query2 = "INSERT INTO...";
$db->exec($query2);
$db->commit();
}catch (PDOException $e) {
try { $db->rollBack(); } catch (Exception $e2) {}
}
My question is, does the rollBack() rollbacks all changes caused by both, execute() and exec()? The reason for using exec() is that I have to dynamically create the $query2 and this way it is much easier for me.
Any operations performed between the start of a transaction and the point you do the rollback are reversed. Doesn't matter HOW you did those operations - they'll be rolled back.
Of course, this assumes you're using transaction-capable databases/tables. For instance, if your exec() was done on a MyISAM table in MySQL, and the execute() on an InnODB table, then InnoDB operation will get rolled back, but you're stuck on the MyISAM one.

Categories