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

Can't run transaction #158

Open
bubnenkoff opened this issue Apr 1, 2021 · 8 comments
Open

Can't run transaction #158

bubnenkoff opened this issue Apr 1, 2021 · 8 comments

Comments

@bubnenkoff
Copy link

bubnenkoff commented Apr 1, 2021

I need to insert in DB list of single INSERT statement as single transaction. Like:

Future<dynamic> sqlInsert(Map body) async {
  try {      
        await connection.transaction( (ctx) async {
            await ctx.query("""INSERT INTO "public"."t1" ( "purchaseNumber")  VALUES ( '123');"""); // 
            await ctx.query("""INSERT INTO "public"."t1" ( "purchaseNumber")  VALUES ( '321');"""); //
            await ctx.query("""COMMIT"""); //
         } 
       
       ).timeout(Duration(seconds: 10));

    }
    on PostgreSQLException catch(e)
    {
      writeLog(e.message);
    }    

  }

But I am getting error:

Unhandled exception: TimeoutException after 0:00:10.000000: Future not completed

Same result on:

        connection.transaction( (ctx) {
            ctx.query("""INSERT INTO "public"."сontract_procedure" ( "purchaseNumber")  VALUES ( '1111111111');"""); // to add ; to the end of every query
            ctx.query("""INSERT INTO "public"."сontract_procedure" ( "purchaseNumber")  VALUES ( '11111111211');"""); // to add ; to the end of every query
            ctx.query("""COMMIT"""); // to add ; to the end of every query     
         } 

What I am missing?

@isoos
Copy link
Collaborator

isoos commented Apr 1, 2021

@bubnenkoff: you don't need to call COMMIT in the transaction((ctx) {}) callback. Unspecified callbacks will call commit when the queries return without issues, or, if you need manual abort on the transaction, you can call ctx.cancelTransaction().

@bubnenkoff
Copy link
Author

bubnenkoff commented Apr 1, 2021

@isoos Do you mean I need to add some callback (that currently not in code)?

@isoos
Copy link
Collaborator

isoos commented Apr 1, 2021

You already do have a callback: (ctx) {} is a function that gets called when the transaction is ready.

@bubnenkoff
Copy link
Author

bubnenkoff commented Apr 1, 2021

@isoos Thanks, but how to detect it was error in transaction?

PostgreSQLSeverity.error : Query failed prior to execution. This query's transaction encountered an error earlier in the transaction that prevented this query from executing.

it's not exception, so I can't handle it.

How to from next method check if all ok, or there was an error?

await connection.transaction( (ctx) {
   for (var s in body['sql'].split(';')) {
        ctx.query(s + ";");  
    }
    // was it complete?
 } 

@isoos
Copy link
Collaborator

isoos commented Apr 1, 2021

use async and await:

  • (ctx) async {
  • await ctx.query(s);

@bubnenkoff
Copy link
Author

bubnenkoff commented Apr 1, 2021

And try-catch inside it? Like:

        await connection.transaction( (ctx) async {
           for (var s in body['sql'].split(';')) {
              // print(s + ";");
              try {
                  await ctx.query(s + ";"); 
              } // catch
               
            }
            
         } 

@isoos
Copy link
Collaborator

isoos commented Apr 1, 2021

Depends on what you want. You should be able to get the exception propagated to the connection.transaction block too, if you execute them in sequence (== with await).

@bubnenkoff
Copy link
Author

bubnenkoff commented Apr 2, 2021

Big thanks! Could you look at next code and say if I understand all that you said right:

  Future<dynamic> sqlInsert(Map body) async {
  try {
      print("Trying to inserting data");
      print("sql: ${body['sql']}");
        // comma separated inserts as list
        await connection.transaction( (ctx) async {
           for (var s in body['sql']) {
              try {
                  await ctx.query(s); 
              } catch (e) {
                print("cancelTransaction was called");
                connection.cancelTransaction();
              } 
            }  
         });

    }
    on PostgreSQLException catch(e)
    {
       print("There is some duplicates. Removing them in new transaction");
        await connection.transaction( (ctx) async {
           for (var s in body['sql-remove']) { // sql-remove have DELETE queries
              try {
                  await ctx.query(s); 
              } catch (e) {
                // something wrong with removing
              } 
            }  
         });

      writeLog("sqlInsert ", e.message);
    }    

    catch (e) {
        writeLog("11sqlInsert ", e.message);
    }

     return 0; 

  }

Or it should be:

        try { 
            await connection.transaction( (ctx) async {
              for (var s in body['sql']) {
                   await ctx.query(s); 
                }  
              });
          } catch (e) {
              print("cancelTransaction was called");
              await connection.cancelTransaction();
              } 

?

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

2 participants