@@ -70,6 +70,8 @@ pub enum StoreError {
7070 WriteFailure ( String , BlockNumber , String , String ) ,
7171 #[ error( "database query timed out" ) ]
7272 StatementTimeout ,
73+ #[ error( "database constraint violated: {0}" ) ]
74+ ConstraintViolation ( String ) ,
7375}
7476
7577// Convenience to report an internal error
@@ -127,6 +129,7 @@ impl Clone for StoreError {
127129 Self :: WriteFailure ( arg0. clone ( ) , arg1. clone ( ) , arg2. clone ( ) , arg3. clone ( ) )
128130 }
129131 Self :: StatementTimeout => Self :: StatementTimeout ,
132+ Self :: ConstraintViolation ( arg0) => Self :: ConstraintViolation ( arg0. clone ( ) ) ,
130133 }
131134 }
132135}
@@ -135,6 +138,7 @@ impl StoreError {
135138 pub fn from_diesel_error ( e : & DieselError ) -> Option < Self > {
136139 const CONN_CLOSE : & str = "server closed the connection unexpectedly" ;
137140 const STMT_TIMEOUT : & str = "canceling statement due to statement timeout" ;
141+ const UNIQUE_CONSTR : & str = "duplicate key value violates unique constraint" ;
138142 let DieselError :: DatabaseError ( _, info) = e else {
139143 return None ;
140144 } ;
@@ -146,6 +150,12 @@ impl StoreError {
146150 Some ( StoreError :: DatabaseUnavailable )
147151 } else if info. message ( ) . contains ( STMT_TIMEOUT ) {
148152 Some ( StoreError :: StatementTimeout )
153+ } else if info. message ( ) . contains ( UNIQUE_CONSTR ) {
154+ let msg = match info. details ( ) {
155+ Some ( details) => format ! ( "{}: {}" , info. message( ) , details. replace( '\n' , " " ) ) ,
156+ None => info. message ( ) . to_string ( ) ,
157+ } ;
158+ Some ( StoreError :: ConstraintViolation ( msg) )
149159 } else {
150160 None
151161 }
@@ -174,7 +184,8 @@ impl StoreError {
174184 | UnknownTable ( _)
175185 | UnknownAttribute ( _, _)
176186 | InvalidIdentifier ( _)
177- | UnsupportedFilter ( _, _) => true ,
187+ | UnsupportedFilter ( _, _)
188+ | ConstraintViolation ( _) => true ,
178189
179190 // non-deterministic errors
180191 Unknown ( _)
0 commit comments