gssj85's avatar

How to disable Save Points?

I'm using Firebird with this lib: https://github.com/harrygulliford/laravel-firebird

As far I understand this lib doesn't have support for transactions.

I had a problem while running nested transactions inside a foreach that when thrown an exception in the "parent" transaction scope it rolled back only the last one inserted in the foreach.

Digging deep I found that here: vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php

It calls the method $this->queryGrammar->supportsSavepoints and it's fixed a "true".

If I modify it to return false (since I believe the lib didn't support anyway) then everything works as expected.

Since I'm not that great of a programmer I'm here to ask if should I do it? and more important how? I'm not sure how to do it without editing the vendor which isn't really the way to go I believe.

Heres the code I used to test the behavior:

public function store(FaturamentoStoreRequest $request)//: FaturamentoResource
    {

        try {
            Transaction::start();
            Cidade::create(['NOME' => 'CIDADE PAI']);

            for ($i = 0; $i < 10; $i++) {
                $this->novaTransacao($i);
            }
            throw new \Exception('asdfg');
            Transaction::commit();
        } catch (\Throwable $th) {

            Transaction::rollback('rolou back');
            throw $th;
        }

        return response()->json(['Ok']);

    }

    private function novaTransacao($i)
    {
        try {
            Transaction::start();
            Cidade::create(['NOME' => 'CIDADE F1 ' . $i]);
            $this->novaTransacao2($i);
            Transaction::commit();
        } catch (\Throwable $th) {
            Transaction::rollback($th->getMessage());
            throw $th;
        }
    }

    private function novaTransacao2($i)
    {
        try {
            Transaction::start();
            Cidade::create(['NOME' => 'CIDADE F2 ' . ($i + 1)]);
//            if ($i = 2) {
//                throw new \Exception('asdfg');
//            }
            Transaction::commit();
        } catch (\Throwable $th) {
            Transaction::rollback($th->getMessage());
            throw $th;
        }
    }

It's strange because it happens only inside a foreach and it is indeed respecting the transaction levels (only really commit (doCommit) when transaction level = 1.

Since it's Firebird and lib doesnt have support for Transactions we created this lib to make it sort of work:

class Transaction
{
    public static function start()
    {

        DB::getPdo()->setAttribute(PDO::ATTR_AUTOCOMMIT, 0);

        DB::beginTransaction();
    }

    public static function commit()
    {
        DB::commit();

        DB::getPdo()->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
    }

    public static function rollback()
    {
        DB::rollback();

        DB::getPdo()->setAttribute(PDO::ATTR_AUTOCOMMIT, 1);
    }
}

Any insight is very welcome, thanks in advance.

0 likes
0 replies

Please or to participate in this conversation.