Skip to content

Commit 4b206ed

Browse files
committed
Throw ProtocolException when QueryType is unknown or missing
This update ensures that `ProtocolException` is thrown when server provides an unknown `QueryType`.
1 parent df8b781 commit 4b206ed

File tree

7 files changed

+116
-66
lines changed

7 files changed

+116
-66
lines changed

driver/src/main/java/org/neo4j/driver/internal/handlers/LegacyPullAllResponseHandler.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.neo4j.driver.Query;
3131
import org.neo4j.driver.Record;
3232
import org.neo4j.driver.Value;
33+
import org.neo4j.driver.exceptions.Neo4jException;
3334
import org.neo4j.driver.internal.InternalRecord;
3435
import org.neo4j.driver.internal.messaging.request.PullAllMessage;
3536
import org.neo4j.driver.internal.spi.Connection;
@@ -92,12 +93,27 @@ public boolean canManageAutoRead()
9293
public synchronized void onSuccess( Map<String,Value> metadata )
9394
{
9495
finished = true;
95-
summary = extractResultSummary( metadata );
96+
Neo4jException exception = null;
97+
try
98+
{
99+
summary = extractResultSummary( metadata );
100+
}
101+
catch ( Neo4jException e )
102+
{
103+
exception = e;
104+
}
96105

97-
completionListener.afterSuccess( metadata );
106+
if ( exception == null )
107+
{
108+
completionListener.afterSuccess( metadata );
98109

99-
completeRecordFuture( null );
100-
completeFailureFuture( null );
110+
completeRecordFuture( null );
111+
completeFailureFuture( null );
112+
}
113+
else
114+
{
115+
onFailure( exception );
116+
}
101117
}
102118

103119
@Override
@@ -335,7 +351,7 @@ private boolean completeFailureFuture( Throwable error )
335351
private ResultSummary extractResultSummary( Map<String,Value> metadata )
336352
{
337353
long resultAvailableAfter = runResponseHandler.resultAvailableAfter();
338-
return metadataExtractor.extractSummary(query, connection, resultAvailableAfter, metadata );
354+
return metadataExtractor.extractSummary( query, connection, resultAvailableAfter, metadata );
339355
}
340356

341357
private void enableAutoRead()

driver/src/main/java/org/neo4j/driver/internal/handlers/pulln/BasicPullResponseHandler.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.neo4j.driver.Query;
2525
import org.neo4j.driver.Record;
2626
import org.neo4j.driver.Value;
27+
import org.neo4j.driver.exceptions.Neo4jException;
2728
import org.neo4j.driver.internal.InternalRecord;
2829
import org.neo4j.driver.internal.handlers.PullResponseCompletionListener;
2930
import org.neo4j.driver.internal.handlers.RunResponseHandler;
@@ -112,9 +113,18 @@ protected void completeWithFailure( Throwable error )
112113
protected void completeWithSuccess( Map<String,Value> metadata )
113114
{
114115
completionListener.afterSuccess( metadata );
115-
ResultSummary summary = extractResultSummary( metadata );
116-
117-
complete( summary, null );
116+
ResultSummary summary;
117+
Neo4jException exception = null;
118+
try
119+
{
120+
summary = extractResultSummary( metadata );
121+
}
122+
catch ( Neo4jException e )
123+
{
124+
summary = extractResultSummary( emptyMap() );
125+
exception = e;
126+
}
127+
complete( summary, exception );
118128
}
119129

120130
protected void successHasMore()

driver/src/main/java/org/neo4j/driver/internal/util/MetadataExtractor.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@
2121
import java.util.Collections;
2222
import java.util.List;
2323
import java.util.Map;
24+
import java.util.function.Function;
2425

2526
import org.neo4j.driver.Bookmark;
2627
import org.neo4j.driver.Query;
2728
import org.neo4j.driver.Value;
29+
import org.neo4j.driver.exceptions.ProtocolException;
2830
import org.neo4j.driver.exceptions.UntrustedServerException;
2931
import org.neo4j.driver.internal.InternalBookmark;
3032
import org.neo4j.driver.internal.spi.Connection;
@@ -49,6 +51,9 @@
4951
public class MetadataExtractor
5052
{
5153
public static final int ABSENT_QUERY_ID = -1;
54+
private static final String UNEXPECTED_TYPE_MSG_FMT = "Unexpected query type '%s', consider updating the driver";
55+
private static final Function<String,ProtocolException> UNEXPECTED_TYPE_EXCEPTION_SUPPLIER =
56+
( type ) -> new ProtocolException( String.format( UNEXPECTED_TYPE_MSG_FMT, type ) );
5257
private final String resultAvailableAfterMetadataKey;
5358
private final String resultConsumedAfterMetadataKey;
5459

@@ -98,14 +103,14 @@ public long extractResultAvailableAfter( Map<String,Value> metadata )
98103
return -1;
99104
}
100105

101-
public ResultSummary extractSummary(Query query, Connection connection, long resultAvailableAfter, Map<String,Value> metadata )
106+
public ResultSummary extractSummary( Query query, Connection connection, long resultAvailableAfter, Map<String,Value> metadata )
102107
{
103108
ServerInfo serverInfo =
104109
new InternalServerInfo( connection.serverAgent(), connection.serverAddress(), connection.protocol().version() );
105110
DatabaseInfo dbInfo = extractDatabaseInfo( metadata );
106-
return new InternalResultSummary(query, serverInfo, dbInfo, extractQueryType( metadata ), extractCounters( metadata ), extractPlan( metadata ),
107-
extractProfiledPlan( metadata ), extractNotifications( metadata ), resultAvailableAfter,
108-
extractResultConsumedAfter( metadata, resultConsumedAfterMetadataKey ) );
111+
return new InternalResultSummary( query, serverInfo, dbInfo, extractQueryType( metadata ), extractCounters( metadata ), extractPlan( metadata ),
112+
extractProfiledPlan( metadata ), extractNotifications( metadata ), resultAvailableAfter,
113+
extractResultConsumedAfter( metadata, resultConsumedAfterMetadataKey ) );
109114
}
110115

111116
public static DatabaseInfo extractDatabaseInfo( Map<String,Value> metadata )
@@ -151,7 +156,7 @@ private static QueryType extractQueryType( Map<String,Value> metadata )
151156
Value typeValue = metadata.get( "type" );
152157
if ( typeValue != null )
153158
{
154-
return QueryType.fromCode( typeValue.asString() );
159+
return QueryType.fromCode( typeValue.asString(), UNEXPECTED_TYPE_EXCEPTION_SUPPLIER );
155160
}
156161
return null;
157162
}

driver/src/main/java/org/neo4j/driver/summary/QueryType.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
*/
1919
package org.neo4j.driver.summary;
2020

21+
import java.util.function.Function;
22+
2123
import org.neo4j.driver.exceptions.ClientException;
24+
import org.neo4j.driver.exceptions.Neo4jException;
2225

2326
/**
2427
* The type of query executed.
28+
*
2529
* @since 1.0
2630
*/
2731
public enum QueryType
@@ -31,7 +35,16 @@ public enum QueryType
3135
WRITE_ONLY,
3236
SCHEMA_WRITE;
3337

34-
public static QueryType fromCode(String type )
38+
private static final String UNEXPECTED_TYPE_MSG_FMT = "Unknown query type: `%s`.";
39+
private static final Function<String,ClientException> UNEXPECTED_TYPE_EXCEPTION_SUPPLIER =
40+
( type ) -> new ClientException( String.format( UNEXPECTED_TYPE_MSG_FMT, type ) );
41+
42+
public static QueryType fromCode( String type )
43+
{
44+
return fromCode( type, UNEXPECTED_TYPE_EXCEPTION_SUPPLIER );
45+
}
46+
47+
public static QueryType fromCode( String type, Function<String,? extends Neo4jException> exceptionFunction )
3548
{
3649
switch ( type )
3750
{
@@ -44,7 +57,14 @@ public static QueryType fromCode(String type )
4457
case "s":
4558
return QueryType.SCHEMA_WRITE;
4659
default:
47-
throw new ClientException( "Unknown query type: `" + type + "`." );
60+
if ( exceptionFunction != null )
61+
{
62+
throw exceptionFunction.apply( type );
63+
}
64+
else
65+
{
66+
return null;
67+
}
4868
}
4969
}
5070
}

driver/src/test/java/org/neo4j/driver/internal/handlers/PullAllResponseHandlerTestBase.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -617,13 +617,13 @@ void shouldFailListAsyncWhenTransformationFunctionThrows()
617617
RuntimeException error = new RuntimeException( "Hi!" );
618618

619619
CompletionStage<List<Integer>> stage = handler.listAsync( record ->
620-
{
621-
if ( record.get( 1 ).asInt() == 4 )
622-
{
623-
throw error;
624-
}
625-
return 42;
626-
} );
620+
{
621+
if ( record.get( 1 ).asInt() == 4 )
622+
{
623+
throw error;
624+
}
625+
return 42;
626+
} );
627627

628628
RuntimeException e = assertThrows( RuntimeException.class, () -> await( stage ) );
629629
assertEquals( error, e );

driver/src/test/java/org/neo4j/driver/util/TestUtil.java

Lines changed: 43 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -442,45 +442,45 @@ public Void answer( InvocationOnMock invocation )
442442
public static void setupSuccessfulRunAndPull( Connection connection )
443443
{
444444
doAnswer( invocation ->
445-
{
446-
ResponseHandler runHandler = invocation.getArgument( 1 );
447-
runHandler.onSuccess( emptyMap() );
448-
return null;
449-
} ).when( connection ).write( any( RunWithMetadataMessage.class ), any() );
445+
{
446+
ResponseHandler runHandler = invocation.getArgument( 1 );
447+
runHandler.onSuccess( emptyMap() );
448+
return null;
449+
} ).when( connection ).write( any( RunWithMetadataMessage.class ), any() );
450450

451451
doAnswer( invocation ->
452-
{
453-
ResponseHandler pullHandler = invocation.getArgument( 1 );
454-
pullHandler.onSuccess( emptyMap() );
455-
return null;
456-
} ).when( connection ).writeAndFlush( any( PullMessage.class ), any() );
452+
{
453+
ResponseHandler pullHandler = invocation.getArgument( 1 );
454+
pullHandler.onSuccess( emptyMap() );
455+
return null;
456+
} ).when( connection ).writeAndFlush( any( PullMessage.class ), any() );
457457
}
458458

459459
public static void setupSuccessfulRunRx( Connection connection )
460460
{
461461
doAnswer( invocation ->
462-
{
463-
ResponseHandler runHandler = invocation.getArgument( 1 );
464-
runHandler.onSuccess( emptyMap() );
465-
return null;
466-
} ).when( connection ).writeAndFlush( any( RunWithMetadataMessage.class ), any() );
462+
{
463+
ResponseHandler runHandler = invocation.getArgument( 1 );
464+
runHandler.onSuccess( emptyMap() );
465+
return null;
466+
} ).when( connection ).writeAndFlush( any( RunWithMetadataMessage.class ), any() );
467467
}
468468

469469
public static void setupSuccessfulRunAndPull( Connection connection, String query )
470470
{
471471
doAnswer( invocation ->
472-
{
473-
ResponseHandler runHandler = invocation.getArgument( 1 );
474-
runHandler.onSuccess( emptyMap() );
475-
return null;
476-
} ).when( connection ).write( argThat( runWithMetaMessageWithQueryMatcher( query ) ), any() );
472+
{
473+
ResponseHandler runHandler = invocation.getArgument( 1 );
474+
runHandler.onSuccess( emptyMap() );
475+
return null;
476+
} ).when( connection ).write( argThat( runWithMetaMessageWithQueryMatcher( query ) ), any() );
477477

478478
doAnswer( invocation ->
479-
{
480-
ResponseHandler pullHandler = invocation.getArgument( 1 );
481-
pullHandler.onSuccess( emptyMap() );
482-
return null;
483-
} ).when( connection ).writeAndFlush( any( PullMessage.class ), any() );
479+
{
480+
ResponseHandler pullHandler = invocation.getArgument( 1 );
481+
pullHandler.onSuccess( emptyMap() );
482+
return null;
483+
} ).when( connection ).writeAndFlush( any( PullMessage.class ), any() );
484484
}
485485

486486
public static Connection connectionMock()
@@ -545,16 +545,16 @@ public static void sleep( int millis )
545545
public static void interruptWhenInWaitingState( Thread thread )
546546
{
547547
CompletableFuture.runAsync( () ->
548-
{
549-
// spin until given thread moves to WAITING state
550-
do
551-
{
552-
sleep( 500 );
553-
}
554-
while ( thread.getState() != Thread.State.WAITING );
548+
{
549+
// spin until given thread moves to WAITING state
550+
do
551+
{
552+
sleep( 500 );
553+
}
554+
while ( thread.getState() != Thread.State.WAITING );
555555

556-
thread.interrupt();
557-
} );
556+
thread.interrupt();
557+
} );
558558
}
559559

560560
public static String randomString( int size )
@@ -609,11 +609,11 @@ private static void assertNoCircularReferences(Throwable ex, List<Throwable> lis
609609
private static void setupSuccessResponse( Connection connection, Class<? extends Message> messageType )
610610
{
611611
doAnswer( invocation ->
612-
{
613-
ResponseHandler handler = invocation.getArgument( 1 );
614-
handler.onSuccess( emptyMap() );
615-
return null;
616-
} ).when( connection ).writeAndFlush( any( messageType ), any() );
612+
{
613+
ResponseHandler handler = invocation.getArgument( 1 );
614+
handler.onSuccess( emptyMap() );
615+
return null;
616+
} ).when( connection ).writeAndFlush( any( messageType ), any() );
617617
}
618618

619619
private static void cleanDb( Session session )
@@ -629,10 +629,10 @@ private static void cleanDb( Session session )
629629
private static int deleteBatchOfNodes( Session session )
630630
{
631631
return session.writeTransaction( tx ->
632-
{
633-
Result result = tx.run( "MATCH (n) WITH n LIMIT 1000 DETACH DELETE n RETURN count(n)" );
634-
return result.single().get( 0 ).asInt();
635-
} );
632+
{
633+
Result result = tx.run( "MATCH (n) WITH n LIMIT 1000 DETACH DELETE n RETURN count(n)" );
634+
return result.single().get( 0 ).asInt();
635+
} );
636636
}
637637

638638
private static Number read( ByteBuf buf, Class<? extends Number> type )

testkit-backend/src/main/java/neo4j/org/testkit/backend/messages/requests/StartTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public class StartTest implements TestkitRequest
4141

4242
static
4343
{
44-
COMMON_SKIP_PATTERN_TO_REASON.put( "^.*\\.test_invalid_query_type$", "Does not report type exception" );
4544
COMMON_SKIP_PATTERN_TO_REASON.put( "^.*\\.test_no_notifications$", "An empty list is returned when there are no notifications" );
4645
COMMON_SKIP_PATTERN_TO_REASON.put( "^.*\\.test_no_notification_info$", "An empty list is returned when there are no notifications" );
4746
COMMON_SKIP_PATTERN_TO_REASON.put( "^.*\\.test_notifications_without_position$", "Null value is provided when position is absent" );

0 commit comments

Comments
 (0)