1
public Mono<String> queryValidation(String connectionId, String query) {
    return connectionConfigRepository.findByConnectionId(connectionId)
        .switchIfEmpty(Mono.error(new RuntimeException("Connection not found: " + connectionId)))
        .flatMap(config -> {
            DatabaseConnectionDetails details = config.getDatabaseConnectionDetails();

            return createConnectionFactory(details)
                .flatMap(factory -> Mono.from(factory.create())
                    .flatMap(conn -> {
                        String escaped = query.replace("'", "''");
                        String validationQuery = "EXEC sp_describe_first_result_set N'" + escaped + "', NULL, 1;";

                        return Flux.from(conn.createStatement(validationQuery).execute())
                            .flatMap(result -> Flux.from(result.map((row, meta) -> "ok"))) // force row parsing
                            .then(Mono.just("Valid Query"))
                            .onErrorResume(e -> Mono.just("Invalid Query: " + e.getMessage()))
                            .doFinally(signal -> conn.close());
                    })
                );
        });
}

I tried this way where I am utilising the .execute() to get the errors and differentiate between a valid and an invalid query but unfortunately its giving me "positive response" in both cases. Its because even Invalid Queries are executed and they return errors along with a success token.

I need to find a way to validate mssql queries, manual Validation will take a lot of time and resources.

Also i tried JSQLParser, but for some reason it didn't work. Any suggestions or advices?

2
  • 1
    This seems like the wrong approach. Queries can fail even if they are written properly, so checking the syntax of the query might still result in problems. You should focus on getting a proper error response when there is one. If it is somehow hidden, that is your problem which needs addressing. Commented Sep 2 at 9:52
  • The query is also at risk from SQL Injection. It should use parameterised queries. Commented Sep 2 at 9:57

1 Answer 1

0

You can use SET NOEXEC ON and afterwards turn it off. Like:

String validationBatch = "SET NOEXEC ON; " + query + "; SET NOEXEC OFF;";

This way you give can only process if the query is valid and it compiles and then you can detect any server errors during compilation.

Always turn NOEXEC off afterwards.

This is edited code:

public Mono<String> validateQuery(String connectionId, String query) {
  return connectionConfigRepository.findByConnectionId(connectionId)
      .switchIfEmpty(Mono.error(new RuntimeException("Connection not found: " + connectionId)))
      .flatMap(cfg -> createConnectionFactory(cfg.getDatabaseConnectionDetails()))
      .flatMap(factory -> Mono.usingWhen(
          Mono.from(factory.create()),
          conn -> {
            String validationBatch = "SET NOEXEC ON; " + query + "; SET NOEXEC OFF;";
            return Flux.from(conn.createStatement(validationBatch).execute())
                .flatMap(result -> Mono.firstWithSignal(
                    result.getRowsUpdated().onErrorResume(__ -> Mono.empty()),
                    result.map((row, md) -> 1).count().thenReturn(0)
                ))
                .then(Mono.just("Valid Query"))
                .onErrorResume(e -> Mono.just("Invalid Query: " + e.getMessage()));
          },
          conn -> Mono.from(conn.close())
      ));
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.