@@ -810,34 +810,29 @@ cdef class CoreProtocol:
810
810
self .transport.writelines(buffers)
811
811
812
812
cdef _execute_many_rollback(self , object error):
813
- cdef:
814
- WriteBuffer packet
815
- WriteBuffer buf
813
+ cdef WriteBuffer buf
816
814
817
815
self ._ensure_connected()
818
816
if self .state != PROTOCOL_CANCELLED:
819
817
self ._set_state(PROTOCOL_BIND_EXECUTE_MANY_ROLLBACK)
820
- packet = WriteBuffer.new()
821
-
822
- # We have no idea if we are in an explicit transaction or not,
823
- # therefore we raise an exception in the database to mark current
824
- # transaction as failed anyway to prevent partial commit
825
- buf = self ._build_parse_message(' ' ,
826
- ' DO language plpgsql $$ BEGIN '
827
- ' RAISE transaction_rollback; '
828
- ' END$$;' )
829
- packet.write_buffer(buf)
830
- buf = self ._build_bind_message(' ' , ' ' , WriteBuffer.new())
831
- packet.write_buffer(buf)
832
- buf = self ._build_execute_message(' ' , 0 )
833
- packet.write_buffer(buf)
834
- packet.write_bytes(SYNC_MESSAGE)
835
-
836
- self .transport.write(memoryview(packet))
837
818
838
819
self .result_type = RESULT_FAILED
839
820
self .result = error
840
821
822
+ # We shall rollback in an implicit transaction to prevent partial
823
+ # commit, while do nothing in an explicit transaction and leaving the
824
+ # error to the user
825
+ if self .xact_status == PQTRANS_IDLE:
826
+ buf = WriteBuffer.new_message(b' Q' )
827
+ # ROLLBACK here won't cause server to send RowDescription,
828
+ # CopyInResponse or CopyOutResponse which we are not expecting, but
829
+ # the server will send ReadyForQuery which finishes executemany()
830
+ buf.write_str(' ROLLBACK;' , self .encoding)
831
+ buf.end_message()
832
+ self ._write(buf)
833
+ else :
834
+ self ._write_sync_message()
835
+
841
836
cdef _execute_many_end(self , object sync):
842
837
if sync is True :
843
838
self ._write_sync_message()
0 commit comments