diff --git a/lib/PgSQL_Session.cpp b/lib/PgSQL_Session.cpp index 4a41ab671..91fe82def 100644 --- a/lib/PgSQL_Session.cpp +++ b/lib/PgSQL_Session.cpp @@ -2939,13 +2939,29 @@ handler_again: } } } - // Swtich to fast forward mode if the query matches copy ... stdin command - re2::StringPiece matched; - const char* query_to_match = (CurrentQuery.get_digest_text() ? CurrentQuery.get_digest_text() : (char*)CurrentQuery.QueryPointer); - if (copy_cmd_matcher->match(query_to_match, &matched)) { - switch_normal_to_fast_forward_mode(pkt, std::string(matched.data(), matched.size()), SESSION_FORWARD_TYPE_COPY_FROM_STDIN_STDOUT); - break; - } + if (status == PROCESSING_QUERY || status == PROCESSING_STMT_PREPARE) { + // Swtich to fast forward mode if the query matches copy ... stdin command + re2::StringPiece matched; + const char* query_to_match = (CurrentQuery.get_digest_text() ? CurrentQuery.get_digest_text() : (char*)CurrentQuery.QueryPointer); + if (copy_cmd_matcher->match(query_to_match, &matched)) { + + if (status == PROCESSING_STMT_PREPARE) { + reset_extended_query_frame(); + proxy_error("'%s' command is not supported in Extended Query protocol mode. Use Simple Query mode to run this command\n", + query_to_match ? query_to_match : ""); + client_myds->setDSS_STATE_QUERY_SENT_NET(); + client_myds->myprot.generate_error_packet(true, true, "Feature not supported", PGSQL_ERROR_CODES::ERRCODE_FEATURE_NOT_SUPPORTED, + false, true); + RequestEnd(myds); + finishQuery(myds, myconn, false); + goto __exit_DSS__STATE_NOT_INITIALIZED; + } + + switch_normal_to_fast_forward_mode(pkt , std::string(matched.data(), matched.size()), SESSION_FORWARD_TYPE_COPY_FROM_STDIN_STDOUT); + break; + } + } + if (myconn->async_state_machine == ASYNC_IDLE) { SetQueryTimeout(); } diff --git a/test/tap/tests/pgsql-unsupported_feature_test-t.cpp b/test/tap/tests/pgsql-unsupported_feature_test-t.cpp index bfcbd0538..c2667f543 100644 --- a/test/tap/tests/pgsql-unsupported_feature_test-t.cpp +++ b/test/tap/tests/pgsql-unsupported_feature_test-t.cpp @@ -105,6 +105,26 @@ void check_copy_binary(PGconn* conn) { PQclear(res); } +void check_copy_stdin_via_extended_query(PGconn* conn) { + PGresult* res = PQprepare(conn, + "copy_stmt", + "COPY mytable FROM STDIN", + 0, + NULL); + + ExecStatusType status = PQresultStatus(res); + + /* Check that it failed */ + ok(status == PGRES_FATAL_ERROR, "PQprepare fails for COPY FROM STDIN"); + + const char* sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE); + + ok(sqlstate && strcmp(sqlstate, "0A000") == 0, + "SQLSTATE is 0A000 (feature_not_supported)"); + + PQclear(res); +} + void execute_tests(bool with_ssl) { PGconn* conn = create_new_connection(with_ssl); @@ -117,14 +137,16 @@ void execute_tests(bool with_ssl) { // Test 2: COPY in binary mode //check_copy_binary(conn); - // Close the connection + // Test 3: COPY FROM STDIN via extended query + check_copy_stdin_via_extended_query(conn); + // Close the connection PQfinish(conn); } int main(int argc, char** argv) { - plan(1); // Total number of tests planned + plan(3); // Total number of tests planned if (cl.getEnv()) return exit_status();