@@ -1046,10 +1046,9 @@ public void signUpMultipleViaBulkImport_Transaction(TransactionConnection connec
1046
1046
try {
1047
1047
Connection sqlConnection = (Connection ) connection .getConnection ();
1048
1048
EmailPasswordQueries .signUpMultipleForBulkImport_Transaction (this , sqlConnection , users );
1049
- } catch (StorageQueryException | SQLException | StorageTransactionLogicException e ) {
1049
+ } catch (StorageQueryException | StorageTransactionLogicException e ) {
1050
1050
Throwable actual = e .getCause ();
1051
- if (actual instanceof BatchUpdateException ) {
1052
- BatchUpdateException batchUpdateException = (BatchUpdateException ) actual ;
1051
+ if (actual instanceof BatchUpdateException batchUpdateException ) {
1053
1052
Map <String , Exception > errorByPosition = new HashMap <>();
1054
1053
SQLException nextException = batchUpdateException .getNextException ();
1055
1054
while (nextException != null ) {
@@ -1271,6 +1270,15 @@ public void updateIsEmailVerified_Transaction(AppIdentifier appIdentifier, Trans
1271
1270
}
1272
1271
}
1273
1272
1273
+ /**
1274
+ * Update the isEmailVerified column for multiple users in the email verification table. This method is used in the
1275
+ * Bulk Migration process.
1276
+ * Important note: this method expects a Map of email to userId, but if there is an error in the batch processing,
1277
+ * it will throw a BulkImportBatchInsertException with a map of userid to Exception, based on the position of the
1278
+ * erroneous item in the batch.
1279
+ * This means, that the underlying map implementation must be one that preserves iteration order (LinkedHashMap
1280
+ * is a good choice) and this is the responsibility of the caller to ensure that the passed map is such.
1281
+ */
1274
1282
@ Override
1275
1283
public void updateMultipleIsEmailVerified_Transaction (AppIdentifier appIdentifier , TransactionConnection con ,
1276
1284
Map <String , String > emailToUserId , boolean isEmailVerified )
@@ -1280,23 +1288,35 @@ public void updateMultipleIsEmailVerified_Transaction(AppIdentifier appIdentifie
1280
1288
EmailVerificationQueries .updateMultipleUsersIsEmailVerified_Transaction (this , sqlCon , appIdentifier ,
1281
1289
emailToUserId , isEmailVerified );
1282
1290
} catch (SQLException e ) {
1283
- if (e instanceof PSQLException ) {
1284
- PostgreSQLConfig config = Config .getConfig (this );
1285
- ServerErrorMessage serverMessage = ((PSQLException ) e ).getServerErrorMessage ();
1291
+ if (e instanceof BatchUpdateException batchUpdateException ) {
1292
+ SQLException nextException = batchUpdateException .getNextException ();
1293
+ Map <String , Exception > errorByPosition = new HashMap <>();
1294
+ while (nextException != null ) {
1286
1295
1287
- if (isForeignKeyConstraintError (serverMessage , config .getEmailVerificationTable (), "app_id" )) {
1288
- throw new TenantOrAppNotFoundException (appIdentifier );
1289
- }
1290
- }
1296
+ if (nextException instanceof PSQLException ) {
1297
+ PostgreSQLConfig config = Config .getConfig (this );
1298
+ ServerErrorMessage serverMessage = ((PSQLException ) nextException ).getServerErrorMessage ();
1291
1299
1292
- boolean isPSQLPrimKeyError = e instanceof PSQLException && isPrimaryKeyError (
1293
- ((PSQLException ) e ).getServerErrorMessage (),
1294
- Config .getConfig (this ).getEmailVerificationTable ());
1300
+ int position = getErroneousEntryPosition (batchUpdateException );
1301
+ String userid = ((Map .Entry <String , String >) emailToUserId .entrySet ().toArray ()[position ]).getKey ();
1302
+ if (isNullConstraintError (serverMessage , config .getEmailVerificationTable (), "email" )) {
1303
+ errorByPosition .put (userid , new NullPointerException ("email is null" ));
1304
+ } else if (isPrimaryKeyError (serverMessage , config .getEmailVerificationTable ())) {
1305
+ errorByPosition .put (userid ,
1306
+ new DuplicateEmailException ());
1307
+ }
1308
+ if (isForeignKeyConstraintError (serverMessage , config .getEmailVerificationTable (),
1309
+ "app_id" )) {
1310
+ throw new TenantOrAppNotFoundException (appIdentifier );
1311
+ }
1312
+ }
1295
1313
1296
- if (!isEmailVerified || !isPSQLPrimKeyError ) {
1314
+ nextException = nextException .getNextException ();
1315
+ }
1316
+ throw new StorageQueryException (
1317
+ new BulkImportBatchInsertException ("emailverification errors" , errorByPosition ));
1318
+ }
1297
1319
throw new StorageQueryException (e );
1298
- }
1299
- // we do not throw an error since the email is already verified
1300
1320
}
1301
1321
}
1302
1322
@@ -1499,9 +1519,7 @@ public void importThirdPartyUsers_Transaction(TransactionConnection con,
1499
1519
Connection sqlCon = (Connection ) con .getConnection ();
1500
1520
ThirdPartyQueries .importUser_Transaction (this , sqlCon , usersToImport );
1501
1521
} catch (SQLException e ) {
1502
- Throwable actual = e .getCause ();
1503
- if (actual instanceof BatchUpdateException ) {
1504
- BatchUpdateException batchUpdateException = (BatchUpdateException ) actual ;
1522
+ if (e instanceof BatchUpdateException batchUpdateException ) {
1505
1523
Map <String , Exception > errorByPosition = new HashMap <>();
1506
1524
SQLException nextException = batchUpdateException .getNextException ();
1507
1525
while (nextException != null ) {
@@ -1769,6 +1787,13 @@ private boolean isForeignKeyConstraintError(ServerErrorMessage serverMessage, St
1769
1787
&& serverMessage .getConstraint ().equals (tableName + "_" + columnName + "_fkey" );
1770
1788
}
1771
1789
1790
+ private boolean isNullConstraintError (ServerErrorMessage serverMessage , String tableName , String columnName ) {
1791
+ String [] tableNameParts = tableName .split ("\\ ." );
1792
+ tableName = tableNameParts [tableNameParts .length - 1 ];
1793
+ return serverMessage .getSQLState ().equals ("23502" )
1794
+ && serverMessage .getMessage ().contains ("null value in column \" " + columnName + "\" of relation \" " + tableName + "\" violates not-null constraint" );
1795
+ }
1796
+
1772
1797
private boolean isPrimaryKeyError (ServerErrorMessage serverMessage , String tableName ) {
1773
1798
String [] tableNameParts = tableName .split ("\\ ." );
1774
1799
tableName = tableNameParts [tableNameParts .length - 1 ];
@@ -2098,50 +2123,46 @@ public void importPasswordlessUsers_Transaction(TransactionConnection con,
2098
2123
Connection sqlCon = (Connection ) con .getConnection ();
2099
2124
PasswordlessQueries .importUsers_Transaction (sqlCon , this , users );
2100
2125
} catch (SQLException e ) {
2101
- if (e instanceof BatchUpdateException ) {
2102
- Throwable actual = e .getCause ();
2103
- if (actual instanceof BatchUpdateException ) {
2104
- BatchUpdateException batchUpdateException = (BatchUpdateException ) actual ;
2105
- Map <String , Exception > errorByPosition = new HashMap <>();
2106
- SQLException nextException = batchUpdateException .getNextException ();
2107
- while (nextException != null ) {
2126
+ if (e instanceof BatchUpdateException batchUpdateException ) {
2127
+ Map <String , Exception > errorByPosition = new HashMap <>();
2128
+ SQLException nextException = batchUpdateException .getNextException ();
2129
+ while (nextException != null ) {
2108
2130
2109
- if (nextException instanceof PSQLException ) {
2110
- PostgreSQLConfig config = Config .getConfig (this );
2111
- ServerErrorMessage serverMessage = ((PSQLException ) nextException ).getServerErrorMessage ();
2131
+ if (nextException instanceof PSQLException ) {
2132
+ PostgreSQLConfig config = Config .getConfig (this );
2133
+ ServerErrorMessage serverMessage = ((PSQLException ) nextException ).getServerErrorMessage ();
2112
2134
2113
- int position = getErroneousEntryPosition (batchUpdateException );
2135
+ int position = getErroneousEntryPosition (batchUpdateException );
2114
2136
2115
- if (isPrimaryKeyError (serverMessage , config .getPasswordlessUsersTable ())
2116
- || isPrimaryKeyError (serverMessage , config .getUsersTable ())
2117
- || isPrimaryKeyError (serverMessage , config .getPasswordlessUserToTenantTable ())
2118
- || isPrimaryKeyError (serverMessage , config .getAppIdToUserIdTable ())) {
2119
- errorByPosition .put (users .get (position ).userId , new DuplicateUserIdException ());
2120
- }
2121
- if (isUniqueConstraintError (serverMessage , config .getPasswordlessUserToTenantTable (),
2122
- "email" )) {
2123
- errorByPosition .put (users .get (position ).userId , new DuplicateEmailException ());
2137
+ if (isPrimaryKeyError (serverMessage , config .getPasswordlessUsersTable ())
2138
+ || isPrimaryKeyError (serverMessage , config .getUsersTable ())
2139
+ || isPrimaryKeyError (serverMessage , config .getPasswordlessUserToTenantTable ())
2140
+ || isPrimaryKeyError (serverMessage , config .getAppIdToUserIdTable ())) {
2141
+ errorByPosition .put (users .get (position ).userId , new DuplicateUserIdException ());
2142
+ }
2143
+ if (isUniqueConstraintError (serverMessage , config .getPasswordlessUserToTenantTable (),
2144
+ "email" )) {
2145
+ errorByPosition .put (users .get (position ).userId , new DuplicateEmailException ());
2124
2146
2125
- } else if (isUniqueConstraintError (serverMessage , config .getPasswordlessUserToTenantTable (),
2126
- "phone_number" )) {
2127
- errorByPosition .put (users .get (position ).userId , new DuplicatePhoneNumberException ());
2147
+ } else if (isUniqueConstraintError (serverMessage , config .getPasswordlessUserToTenantTable (),
2148
+ "phone_number" )) {
2149
+ errorByPosition .put (users .get (position ).userId , new DuplicatePhoneNumberException ());
2128
2150
2129
- } else if (isForeignKeyConstraintError (serverMessage , config .getAppIdToUserIdTable (),
2130
- "app_id" )) {
2131
- throw new TenantOrAppNotFoundException (users .get (position ).tenantIdentifier .toAppIdentifier ());
2151
+ } else if (isForeignKeyConstraintError (serverMessage , config .getAppIdToUserIdTable (),
2152
+ "app_id" )) {
2153
+ throw new TenantOrAppNotFoundException (users .get (position ).tenantIdentifier .toAppIdentifier ());
2132
2154
2133
- } else if (isForeignKeyConstraintError (serverMessage , config .getUsersTable (),
2134
- "tenant_id" )) {
2135
- throw new TenantOrAppNotFoundException (users .get (position ).tenantIdentifier .toAppIdentifier ());
2136
- }
2155
+ } else if (isForeignKeyConstraintError (serverMessage , config .getUsersTable (),
2156
+ "tenant_id" )) {
2157
+ throw new TenantOrAppNotFoundException (users .get (position ).tenantIdentifier .toAppIdentifier ());
2137
2158
}
2138
- nextException = nextException .getNextException ();
2139
2159
}
2140
- throw new StorageQueryException (
2141
- new BulkImportBatchInsertException ("passwordless errors" , errorByPosition ));
2160
+ nextException = nextException .getNextException ();
2142
2161
}
2143
- throw new StorageQueryException (e );
2162
+ throw new StorageQueryException (
2163
+ new BulkImportBatchInsertException ("passwordless errors" , errorByPosition ));
2144
2164
}
2165
+ throw new StorageQueryException (e );
2145
2166
}
2146
2167
}
2147
2168
@@ -3627,8 +3648,7 @@ public void addBulkImportUsers(AppIdentifier appIdentifier, List<BulkImportUser>
3627
3648
try {
3628
3649
BulkImportQueries .insertBulkImportUsers_Transaction (this , (Connection ) con .getConnection (), appIdentifier , users );
3629
3650
} catch (SQLException e ) {
3630
- if (e instanceof BatchUpdateException ) {
3631
- BatchUpdateException batchUpdateException = (BatchUpdateException ) e ;
3651
+ if (e instanceof BatchUpdateException batchUpdateException ) {
3632
3652
SQLException nextException = batchUpdateException .getNextException ();
3633
3653
if (nextException instanceof PSQLException ){
3634
3654
ServerErrorMessage serverErrorMessage = ((PSQLException ) nextException ).getServerErrorMessage ();
@@ -3756,6 +3776,7 @@ public List<String> deleteBulkImportUsers(AppIdentifier appIdentifier, @Nonnull
3756
3776
try {
3757
3777
return BulkImportQueries .deleteBulkImportUsers (this , appIdentifier , bulkImportUserIds );
3758
3778
} catch (SQLException e ) {
3779
+ Logging .error (this , "Error deleting bulk import users" , true , e );
3759
3780
throw new StorageQueryException (e );
3760
3781
}
3761
3782
}
0 commit comments