From 17aeafa678d585a478725e404dcbdb4af5b61086 Mon Sep 17 00:00:00 2001
From: Aymeric <aymeric@firebolt.io>
Date: Wed, 22 Mar 2023 13:43:08 +0000
Subject: [PATCH 01/15] Start adding support for new identity

---
 .github/workflows/integration-test.yml        |   7 +-
 .../java/integration/ConnectionInfo.java      |   6 +-
 .../java/integration/IntegrationTest.java     |  24 +-
 .../tests/PreparedStatementTest.java          |   5 +-
 .../java/integration/tests/StatementTest.java |   8 +
 .../java/integration/tests/TimestampTest.java |  12 +
 .../java/com/firebolt/FireboltDriver.java     |   2 +-
 src/main/java/com/firebolt/jdbc/Query.java    |  65 ------
 .../java/com/firebolt/jdbc/QueryResult.java   |   5 +-
 .../firebolt/jdbc/client/FireboltClient.java  |   5 +
 .../client/account/FireboltAccountClient.java | 133 -----------
 .../AuthenticationRequestFactory.java         |  18 --
 .../FireboltAuthenticationClient.java         |   5 +-
 .../ServiceAccountAuthenticationRequest.java  |  39 ++--
 ...UsernamePasswordAuthenticationRequest.java |  35 ---
 .../gateway/FireboltGatewayUrlClient.java     |  38 ++++
 .../client/gateway/GatewayUrlResponse.java    |  15 ++
 .../client/query/StatementClientImpl.java     |   5 +-
 .../jdbc/connection/FireboltConnection.java   |  75 +++++--
 .../jdbc/connection/FireboltJdbcUrlUtil.java  |  52 -----
 .../com/firebolt/jdbc/connection/UrlUtil.java |  44 ++++
 .../settings/FireboltProperties.java          |  37 +++-
 .../settings/FireboltSessionProperty.java     |   6 +-
 .../firebolt/jdbc/metadata/MetadataUtil.java  |  66 +++++-
 .../jdbc/resultset/FireboltResultSet.java     |   2 +-
 .../FireboltAuthenticationService.java        |   2 +-
 .../jdbc/service/FireboltEngineService.java   | 167 +++++++-------
 .../service/FireboltGatewayUrlService.java    |  15 ++
 .../service/FireboltStatementService.java     |   7 +-
 .../jdbc/statement/FireboltStatement.java     |   2 +-
 .../com/firebolt/jdbc/util/PropertyUtil.java  |   4 +-
 .../com/firebolt/jdbc/RawStatementTest.java   |   1 +
 .../account/FireboltAccountClientTest.java    |   3 +
 .../AuthenticationRequestFactoryTest.java     |  32 ---
 .../FireboltAuthenticationClientTest.java     |  10 +-
 ...rviceAccountAuthenticationRequestTest.java |  10 +-
 ...namePasswordAuthenticationRequestTest.java |  40 ----
 .../gateway/FireboltGatewayUrlClientTest.java |  72 ++++++
 .../client/query/StatementClientImplTest.java |  29 ++-
 .../connection/FireboltConnectionTest.java    | 149 ++++++++-----
 .../connection/FireboltJdbcUrlUtilTest.java   |  25 ---
 .../firebolt/jdbc/connection/UrlUtilTest.java |  29 +++
 .../settings/FireboltPropertiesTest.java      |  74 ++++---
 .../FireboltAuthenticationServiceTest.java    |  16 +-
 .../service/FireboltEngineServiceTest.java    | 206 +++++-------------
 .../service/FireboltStatementServiceTest.java |  26 +--
 .../jdbc/statement/FireboltStatementTest.java |  16 +-
 .../FireboltPreparedStatementTest.java        |  28 +--
 .../firebolt/jdbc/util/PropertyUtilTest.java  |   5 +-
 49 files changed, 802 insertions(+), 875 deletions(-)
 delete mode 100644 src/main/java/com/firebolt/jdbc/Query.java
 delete mode 100644 src/main/java/com/firebolt/jdbc/client/account/FireboltAccountClient.java
 delete mode 100644 src/main/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactory.java
 delete mode 100644 src/main/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequest.java
 create mode 100644 src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
 create mode 100644 src/main/java/com/firebolt/jdbc/client/gateway/GatewayUrlResponse.java
 delete mode 100644 src/main/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtil.java
 create mode 100644 src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
 create mode 100644 src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
 delete mode 100644 src/test/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactoryTest.java
 delete mode 100644 src/test/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequestTest.java
 create mode 100644 src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
 delete mode 100644 src/test/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtilTest.java
 create mode 100644 src/test/java/com/firebolt/jdbc/connection/UrlUtilTest.java

diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index 448169567..21cd1a41a 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -7,6 +7,9 @@ on:
         description: 'Database - a new one will be created if not provided'
         required: false
         default: ''
+      account:
+        description: 'Account'
+        required: true
       environment:
         description: 'Environment to run the tests against'
         type: choice
@@ -66,7 +69,7 @@ jobs:
           fi
 
       - name: Run integration tests
-        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Dapi=api.${{ github.event.inputs.environment }}.firebolt.io -Dpassword="${{ env.SERVICE_ACCOUNT_SECRET }}" -Duser="${{ env.SERVICE_ACCOUNT_ID }}"
+        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dpassword="${{ env.SERVICE_ACCOUNT_SECRET }}" -Duser="${{ env.SERVICE_ACCOUNT_ID }} -Daccount=${{ github.event.inputs.account }}"
 
       - name: "Foresight: Analyze Test Results"
         uses: runforesight/foresight-test-kit-action@v1
@@ -77,4 +80,4 @@ jobs:
           test_path: ./build/test-results/
           tags: |
             type:"integration"
-            language:"Java"
+            language:"Java"
\ No newline at end of file
diff --git a/src/integrationTest/java/integration/ConnectionInfo.java b/src/integrationTest/java/integration/ConnectionInfo.java
index 9c1e26127..f4ea57ded 100644
--- a/src/integrationTest/java/integration/ConnectionInfo.java
+++ b/src/integrationTest/java/integration/ConnectionInfo.java
@@ -9,14 +9,16 @@ public class ConnectionInfo {
 	private static ConnectionInfo INSTANCE;
 	String password;
 	String user;
-	String api;
+	String env;
 	String database;
+	String account;
 
 	private ConnectionInfo() {
 		password = Optional.ofNullable(System.getProperty("password")).map(p -> p.replace("\"", "")).orElse(null);
 		user = Optional.ofNullable(System.getProperty("user")).map(u -> u.replace("\"", "")).orElse(null);
-		api = System.getProperty("api");
+		env = System.getProperty("env");
 		database = System.getProperty("db");
+		account = System.getProperty("account");
 	}
 
 	public static ConnectionInfo getInstance() {
diff --git a/src/integrationTest/java/integration/IntegrationTest.java b/src/integrationTest/java/integration/IntegrationTest.java
index aff322ced..29c0a6ebb 100644
--- a/src/integrationTest/java/integration/IntegrationTest.java
+++ b/src/integrationTest/java/integration/IntegrationTest.java
@@ -20,27 +20,29 @@
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
 public abstract class IntegrationTest {
 
+	private static final String JDBC_URL_PREFIX = "jdbc:firebolt:";
+
 	protected Connection createLocalConnection(String queryParams) throws SQLException {
 		return DriverManager.getConnection(
-				"jdbc:firebolt://localhost" + "/" + integration.ConnectionInfo.getInstance().getDatabase()
-						+ queryParams,
+				JDBC_URL_PREFIX + integration.ConnectionInfo.getInstance().getDatabase()
+						+ queryParams + "&host=localhost" + getAccountParam(),
 				integration.ConnectionInfo.getInstance().getUser(),
 				integration.ConnectionInfo.getInstance().getPassword());
 	}
 
 	protected Connection createConnection() throws SQLException {
 		return DriverManager.getConnection(
-				"jdbc:firebolt://" + integration.ConnectionInfo.getInstance().getApi() + "/"
-						+ integration.ConnectionInfo.getInstance().getDatabase(),
+				JDBC_URL_PREFIX
+						+ integration.ConnectionInfo.getInstance().getDatabase() + "?" + getEnvParam() + getAccountParam() ,
 				integration.ConnectionInfo.getInstance().getUser(),
 				integration.ConnectionInfo.getInstance().getPassword());
 	}
 
 	protected Connection createConnection(String engine) throws SQLException {
 		return DriverManager.getConnection(
-				"jdbc:firebolt://" + integration.ConnectionInfo.getInstance().getApi() + "/"
-						+ integration.ConnectionInfo.getInstance().getDatabase()
-						+ Optional.ofNullable(engine).map(e -> "?engine=" + e).orElse(""),
+				JDBC_URL_PREFIX +
+						 integration.ConnectionInfo.getInstance().getDatabase()
+						+ Optional.ofNullable(engine).map(e -> "?" + getEnvParam() +"&engine=" + e + getAccountParam() ).orElse("?" + getEnvParam() + getAccountParam()),
 				integration.ConnectionInfo.getInstance().getUser(),
 				integration.ConnectionInfo.getInstance().getPassword());
 	}
@@ -70,4 +72,12 @@ protected void removeExistingClient() throws NoSuchFieldException, IllegalAccess
 		field.set(null, null);
 	}
 
+	private String getAccountParam() {
+		return "&account=" + integration.ConnectionInfo.getInstance().getAccount();
+	}
+
+	private String getEnvParam() {
+		return "&env=" + integration.ConnectionInfo.getInstance().getEnv();
+	}
+
 }
diff --git a/src/integrationTest/java/integration/tests/PreparedStatementTest.java b/src/integrationTest/java/integration/tests/PreparedStatementTest.java
index 2b5e3f39e..4a775cd20 100644
--- a/src/integrationTest/java/integration/tests/PreparedStatementTest.java
+++ b/src/integrationTest/java/integration/tests/PreparedStatementTest.java
@@ -165,8 +165,9 @@ void shouldFailSQLInjectionAttempt() throws SQLException {
 	private QueryResult createExpectedResult(List<List<?>> expectedRows) {
 		return QueryResult.builder().databaseName(ConnectionInfo.getInstance().getDatabase())
 				.tableName("prepared_statement_test")
-				.columns(Arrays.asList(QueryResult.Column.builder().name("sales").type(FireboltDataType.BIG_INT).build(),
-						QueryResult.Column.builder().name("make").type(FireboltDataType.TEXT).build()))
+				.columns(
+						Arrays.asList(QueryResult.Column.builder().name("sales").type(FireboltDataType.BIG_INT).build(),
+								QueryResult.Column.builder().name("make").type(FireboltDataType.TEXT).build()))
 				.rows(expectedRows).build();
 
 	}
diff --git a/src/integrationTest/java/integration/tests/StatementTest.java b/src/integrationTest/java/integration/tests/StatementTest.java
index 1be46b92e..e9c425595 100644
--- a/src/integrationTest/java/integration/tests/StatementTest.java
+++ b/src/integrationTest/java/integration/tests/StatementTest.java
@@ -29,6 +29,14 @@ void afterEach() {
 		executeStatementFromFile("/statements/statement/cleanup.sql");
 	}
 
+	@Test
+	void shouldSelect1() throws SQLException {
+		try (Connection connection = this.createConnection(); Statement statement = connection.createStatement()) {
+			statement.executeQuery("SELECT 1;");
+			assertNotNull(statement.executeQuery("SELECT 1;"));
+		}
+	}
+
 	@Test
 	void shouldReuseStatementWhenNotCloseOnCompletion() throws SQLException {
 		try (Connection connection = this.createConnection(); Statement statement = connection.createStatement()) {
diff --git a/src/integrationTest/java/integration/tests/TimestampTest.java b/src/integrationTest/java/integration/tests/TimestampTest.java
index ee3f671f7..a62b8bb6e 100644
--- a/src/integrationTest/java/integration/tests/TimestampTest.java
+++ b/src/integrationTest/java/integration/tests/TimestampTest.java
@@ -131,6 +131,18 @@ void shouldRemoveOffsetDIffWhenTimestampOffsetHasChangedCET() throws SQLExceptio
 		}
 	}
 
+	@Test
+	void shouldHaveCorrectInfo() throws SQLException {
+		try (Connection connection = this.createConnection("system");
+			 Statement statement = connection.createStatement();
+			 ResultSet resultSet = statement.executeQuery("SELECT 3::decimal")) {
+			 resultSet.next();
+			 assertEquals(9, resultSet.getMetaData().getScale(1));
+			assertEquals(38, resultSet.getMetaData().getPrecision(1));
+		}
+
+	}
+
 	@Test
 	void shouldReturnTimestampFromTimestampntz() throws SQLException {
 		try (Connection connection = this.createConnection();
diff --git a/src/main/java/com/firebolt/FireboltDriver.java b/src/main/java/com/firebolt/FireboltDriver.java
index e079e62e6..849e59adb 100644
--- a/src/main/java/com/firebolt/FireboltDriver.java
+++ b/src/main/java/com/firebolt/FireboltDriver.java
@@ -17,7 +17,7 @@
 public class FireboltDriver implements Driver {
 
 	public static final String JDBC_FIREBOLT = "jdbc:firebolt:";
-	private static final String JDBC_FIREBOLT_PREFIX = JDBC_FIREBOLT + "//";
+	private static final String JDBC_FIREBOLT_PREFIX = JDBC_FIREBOLT;
 
 	static {
 		try {
diff --git a/src/main/java/com/firebolt/jdbc/Query.java b/src/main/java/com/firebolt/jdbc/Query.java
deleted file mode 100644
index aa22b74b5..000000000
--- a/src/main/java/com/firebolt/jdbc/Query.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.firebolt.jdbc;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-
-import lombok.Builder;
-import lombok.Value;
-
-/**
- * Represents a SQL query that can be sent to Firebolt
- */
-@Builder
-@Value
-public class Query {
-	String select;
-	String from;
-	String innerJoin;
-	String orderBy;
-	List<String> conditions;
-
-	/**
-	 * Parse the object to a SQL query that can be sent to Firebolt
-	 * 
-	 * @return SQL query that can be sent to Firebolt
-	 */
-	public String toSql() {
-		StringBuilder query = new StringBuilder();
-		if (StringUtils.isBlank(select)) {
-			throw new IllegalStateException("Cannot create query: SELECT cannot be blank");
-		}
-		if (StringUtils.isBlank(from)) {
-			throw new IllegalStateException("Cannot create query: FROM cannot be blank");
-		}
-
-		query.append("SELECT ").append(select);
-		query.append(" FROM ").append(from);
-		if (StringUtils.isNotBlank(innerJoin)) {
-			query.append(" JOIN ").append(innerJoin);
-		}
-		query.append(getConditionsPart());
-		if (StringUtils.isNotBlank(orderBy)) {
-			query.append(" order by ").append(orderBy);
-		}
-		return query.toString();
-	}
-
-	private String getConditionsPart() {
-		StringBuilder agg = new StringBuilder();
-		Iterator<String> iter = conditions.iterator();
-		if (iter.hasNext()) {
-			agg.append(" WHERE ");
-		}
-		if (iter.hasNext()) {
-			String entry = iter.next();
-			agg.append(entry);
-		}
-		while (iter.hasNext()) {
-			String entry = iter.next();
-			agg.append(" AND ").append(entry);
-		}
-		return agg.toString();
-	}
-}
diff --git a/src/main/java/com/firebolt/jdbc/QueryResult.java b/src/main/java/com/firebolt/jdbc/QueryResult.java
index 0e2ccddc4..bcdb01dbb 100644
--- a/src/main/java/com/firebolt/jdbc/QueryResult.java
+++ b/src/main/java/com/firebolt/jdbc/QueryResult.java
@@ -13,6 +13,7 @@
 /**
  * Class containing a query result that can be used to create a
  * {@link com.firebolt.jdbc.resultset.FireboltResultSet}
+ * It is particularly useful for metadata methods as a ResulSet containing metadata info must be returned.
  */
 @Builder
 @Value
@@ -36,8 +37,8 @@ public String toString() {
 		StringBuilder stringBuilder = new StringBuilder();
 		this.appendWithListValues(stringBuilder, columns.stream().map(Column::getName).collect(Collectors.toList()));
 		stringBuilder.append(NEXT_LINE);
-		this.appendWithListValues(stringBuilder, columns.stream().map(Column::getType)
-				.map(FireboltDataType::getAliases).map( aliases -> aliases[0]).collect(Collectors.toList()));
+		this.appendWithListValues(stringBuilder, columns.stream().map(Column::getType).map(FireboltDataType::getAliases)
+				.map(aliases -> aliases[0]).collect(Collectors.toList()));
 		stringBuilder.append(NEXT_LINE);
 
 		for (int i = 0; i < rows.size(); i++) {
diff --git a/src/main/java/com/firebolt/jdbc/client/FireboltClient.java b/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
index 5694fbaf1..a520f12f5 100644
--- a/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
+++ b/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
@@ -46,6 +46,11 @@ protected FireboltClient(OkHttpClient httpClient, FireboltConnection connection,
 				customClients != null ? customClients : "");
 	}
 
+	protected <T> T getResource(String uri, String accessToken, Class<T> valueType)
+			throws IOException, FireboltException {
+		return getResource(uri, uri, accessToken, valueType);
+	}
+
 	protected <T> T getResource(String uri, String host, String accessToken, Class<T> valueType)
 			throws IOException, FireboltException {
 		Request rq = createGetRequest(uri, accessToken);
diff --git a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountClient.java b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountClient.java
deleted file mode 100644
index 0b020a891..000000000
--- a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountClient.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.firebolt.jdbc.client.account;
-
-import java.io.IOException;
-
-import org.apache.commons.lang3.StringUtils;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.firebolt.jdbc.client.FireboltClient;
-import com.firebolt.jdbc.client.account.response.FireboltAccountResponse;
-import com.firebolt.jdbc.client.account.response.FireboltDefaultDatabaseEngineResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineIdResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineResponse;
-import com.firebolt.jdbc.connection.FireboltConnection;
-import com.firebolt.jdbc.exception.ExceptionType;
-import com.firebolt.jdbc.exception.FireboltException;
-
-import lombok.CustomLog;
-import okhttp3.OkHttpClient;
-
-@CustomLog
-public class FireboltAccountClient extends FireboltClient {
-
-	private static final String GET_ACCOUNT_ID_URI = "%s/iam/v2/accounts:getIdByName?accountName=%s";
-	private static final String URI_SUFFIX_ENGINE_AND_ACCOUNT_ID_BY_ENGINE_NAME = "engines:getIdByName?engine_name=";
-	private static final String URI_SUFFIX_ACCOUNT_ENGINE_INFO_BY_ENGINE_ID = "engines/";
-	private static final String URI_SUFFIX_DATABASE_INFO_URL = "engines:getURLByDatabaseName?databaseName=";
-	private static final String URI_PREFIX_WITH_ACCOUNT_RESOURCE = "%s/core/v1/accounts/%s/%s";
-	private static final String URI_PREFIX_WITHOUT_ACCOUNT_RESOURCE = "%s/core/v1/account/%s";
-
-	public FireboltAccountClient(OkHttpClient httpClient, ObjectMapper objectMapper,
-			FireboltConnection fireboltConnection, String customDrivers, String customClients) {
-		super(httpClient, fireboltConnection, customDrivers, customClients, objectMapper);
-	}
-
-	/**
-	 * Returns the account
-	 *
-	 * @param host        the host
-	 * @param account     the name of the account
-	 * @param accessToken the access token
-	 * @return the account
-	 */
-	public FireboltAccountResponse getAccount(String host, String account, String accessToken)
-			throws FireboltException, IOException {
-		String uri = String.format(GET_ACCOUNT_ID_URI, host, account);
-		return getResource(uri, host, accessToken, FireboltAccountResponse.class);
-	}
-
-	/**
-	 * Returns an engine
-	 *
-	 * @param host        the host
-	 * @param accountId   the id of the account
-	 * @param engineName  the engine name
-	 * @param engineId    the engine id
-	 * @param accessToken the access token
-	 * @return the engine
-	 */
-	public FireboltEngineResponse getEngine(String host, String accountId, String engineName, String engineId,
-			String accessToken) throws FireboltException, IOException {
-		try {
-			String uri = createAccountUri(accountId, host, URI_SUFFIX_ACCOUNT_ENGINE_INFO_BY_ENGINE_ID + engineId);
-			return getResource(uri, host, accessToken, FireboltEngineResponse.class);
-		} catch (FireboltException exception) {
-			if (exception.getType() == ExceptionType.RESOURCE_NOT_FOUND) {
-				throw new FireboltException(
-						String.format("The address of the engine with name %s and id %s could not be found", engineName,
-								engineId),
-						exception, ExceptionType.RESOURCE_NOT_FOUND);
-			} else {
-				throw exception;
-			}
-		}
-	}
-
-	/**
-	 * Returns the default engine of the database
-	 *
-	 * @param host        the host
-	 * @param accountId   the account id
-	 * @param dbName      the name of the database
-	 * @param accessToken the access token
-	 * @return the default engine for the database
-	 */
-	public FireboltDefaultDatabaseEngineResponse getDefaultEngineByDatabaseName(String host, String accountId, String dbName,
-																				String accessToken) throws FireboltException, IOException {
-		String uri = createAccountUri(accountId, host, URI_SUFFIX_DATABASE_INFO_URL + dbName);
-		try {
-			return getResource(uri, host, accessToken, FireboltDefaultDatabaseEngineResponse.class);
-
-		} catch (FireboltException exception) {
-			if (exception.getType() == ExceptionType.RESOURCE_NOT_FOUND) {
-				throw new FireboltException(String.format("The database with the name %s could not be found", dbName),
-						exception, ExceptionType.RESOURCE_NOT_FOUND);
-			} else {
-				throw exception;
-			}
-		}
-	}
-
-	/**
-	 * Returns the engine id
-	 *
-	 * @param host        the host
-	 * @param accountId   the account id
-	 * @param engineName  the name of the engine
-	 * @param accessToken the access token
-	 * @return the engine id
-	 */
-	public FireboltEngineIdResponse getEngineId(String host, String accountId, String engineName, String accessToken)
-			throws FireboltException, IOException {
-		try {
-			String uri = createAccountUri(accountId, host,
-					URI_SUFFIX_ENGINE_AND_ACCOUNT_ID_BY_ENGINE_NAME + engineName);
-			return getResource(uri, host, accessToken, FireboltEngineIdResponse.class);
-		} catch (FireboltException exception) {
-			if (exception.getType() == ExceptionType.RESOURCE_NOT_FOUND) {
-				throw new FireboltException(String.format("The engine %s could not be found", engineName), exception,
-						ExceptionType.RESOURCE_NOT_FOUND);
-			} else {
-				throw exception;
-			}
-		}
-	}
-
-	private String createAccountUri(String account, String host, String suffix) {
-		if (StringUtils.isNotEmpty(account))
-			return String.format(URI_PREFIX_WITH_ACCOUNT_RESOURCE, host, account, suffix);
-		else
-			return String.format(URI_PREFIX_WITHOUT_ACCOUNT_RESOURCE, host, suffix);
-	}
-
-}
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactory.java b/src/main/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactory.java
deleted file mode 100644
index 0f432c707..000000000
--- a/src/main/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactory.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.firebolt.jdbc.client.authentication;
-
-import org.apache.commons.lang3.StringUtils;
-
-import lombok.experimental.UtilityClass;
-
-@UtilityClass
-public class AuthenticationRequestFactory {
-
-	public static AuthenticationRequest getAuthenticationRequest(String username, String password, String host) {
-		if (StringUtils.isEmpty(username) || StringUtils.contains(username, "@")) {
-			return new UsernamePasswordAuthenticationRequest(username, password, host);
-		} else {
-			return new ServiceAccountAuthenticationRequest(username, password, host);
-		}
-	}
-
-}
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java b/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
index 3813555a9..a63d00747 100644
--- a/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
+++ b/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
@@ -32,10 +32,9 @@ public FireboltAuthenticationClient(OkHttpClient httpClient, ObjectMapper object
 	 * @param password the password
 	 * @return the connection tokens
 	 */
-	public FireboltConnectionTokens postConnectionTokens(String host, String user, String password)
+	public FireboltConnectionTokens postConnectionTokens(String host, String user, String password, String environment)
 			throws IOException, FireboltException {
-		AuthenticationRequest authenticationRequest = AuthenticationRequestFactory.getAuthenticationRequest(user,
-				password, host);
+		AuthenticationRequest authenticationRequest = new ServiceAccountAuthenticationRequest(user, password, environment);
 		String uri = authenticationRequest.getUri();
 		log.debug("Creating connection with url {}", uri);
 		Request request = this.createPostRequest(uri, authenticationRequest.getRequestBody());
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java b/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
index a6bf99182..4819bbc6a 100644
--- a/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
+++ b/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
@@ -1,27 +1,34 @@
 package com.firebolt.jdbc.client.authentication;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
 import lombok.AllArgsConstructor;
 import okhttp3.FormBody;
 import okhttp3.RequestBody;
 
 @AllArgsConstructor
 public class ServiceAccountAuthenticationRequest implements AuthenticationRequest {
-	private static final String CLIENT_CREDENTIALS = "client_credentials";
-	private static final String GRAND_TYPE_FIELD_NAME = "grant_type";
-	private static final String CLIENT_ID_FIELD_NAME = "client_id";
-	private static final String CLIENT_SECRET_FIELD_NAME = "client_secret";
-	private static final String AUTH_URL = "%s/auth/v1/token";
-	private String id;
-	private String secret;
-	private String host;
 
-	public RequestBody getRequestBody() {
-		return new FormBody.Builder().add(CLIENT_ID_FIELD_NAME, id).add(CLIENT_SECRET_FIELD_NAME, secret)
-				.add(GRAND_TYPE_FIELD_NAME, CLIENT_CREDENTIALS).build();
-	}
+    private static final String AUDIENCE_FIELD_NAME = "audience";
+    private static final String GRAND_TYPE_FIELD_NAME = "grant_type";
+    private static final String GRAND_TYPE_FIELD_VALUE = "client_credentials";
+    private static final String CLIENT_ID_FIELD_NAME = "client_id";
+    private static final String CLIENT_SECRET_FIELD_NAME = "client_secret";
+    private static final String AUTH_URL = "https://id.%s.firebolt.io/oauth/token";
 
-	@Override
-	public String getUri() {
-		return String.format(AUTH_URL, host);
-	}
+    private final String clientId;
+    private final String clientSecret;
+    private final String environment;
+
+    @Override
+    public RequestBody getRequestBody() throws JsonProcessingException {
+        return new FormBody.Builder().add(AUDIENCE_FIELD_NAME, String.format("https://%s-firebolt-v2.us.auth0.com/api/v2/", environment))
+                .add(GRAND_TYPE_FIELD_NAME, GRAND_TYPE_FIELD_VALUE)
+                .add(CLIENT_ID_FIELD_NAME, clientId)
+                .add(CLIENT_SECRET_FIELD_NAME, clientSecret).build();
+    }
+
+    @Override
+    public String getUri() {
+        return String.format(AUTH_URL, environment);
+    }
 }
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequest.java b/src/main/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequest.java
deleted file mode 100644
index 1ef2b31e9..000000000
--- a/src/main/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.firebolt.jdbc.client.authentication;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.firebolt.jdbc.client.FireboltObjectMapper;
-
-import lombok.AllArgsConstructor;
-import okhttp3.MediaType;
-import okhttp3.RequestBody;
-
-@AllArgsConstructor
-public class UsernamePasswordAuthenticationRequest implements AuthenticationRequest {
-	private static final String AUTH_URL = "%s/auth/v1/login";
-	private static final String USERNAME_FIELD_NAME = "username";
-	private static final String PASSWORD_FIELD_NAME = "password";
-	private String username;
-	private String password;
-	private String host;
-
-	public RequestBody getRequestBody() throws JsonProcessingException {
-		Map<String, Object> loginDetailsMap = new HashMap<>();
-		loginDetailsMap.put(USERNAME_FIELD_NAME, username);
-		loginDetailsMap.put(PASSWORD_FIELD_NAME, password);
-		return RequestBody.create(FireboltObjectMapper.getInstance().writeValueAsString(loginDetailsMap),
-				MediaType.parse("application/json"));
-	}
-
-	@Override
-	public String getUri() {
-		return String.format(AUTH_URL, host);
-	}
-
-}
\ No newline at end of file
diff --git a/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java b/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
new file mode 100644
index 000000000..e65850cbd
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
@@ -0,0 +1,38 @@
+package com.firebolt.jdbc.client.gateway;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.firebolt.jdbc.client.FireboltClient;
+import com.firebolt.jdbc.connection.FireboltConnection;
+import com.firebolt.jdbc.exception.FireboltException;
+import lombok.CustomLog;
+import okhttp3.OkHttpClient;
+
+@CustomLog
+public class FireboltGatewayUrlClient extends FireboltClient {
+
+    private static final String URL = "https://api.dev.firebolt.io/web/v3/account/%s/engineUrl";
+
+    public FireboltGatewayUrlClient(OkHttpClient httpClient, ObjectMapper objectMapper,
+                                    FireboltConnection fireboltConnection, String customDrivers, String customClients) {
+        super(httpClient, fireboltConnection, customDrivers, customClients, objectMapper);
+    }
+
+    /**
+     * Returns the gateway URL
+     *
+     * @param accessToken the access token
+     * @return the account
+     */
+    public GatewayUrlResponse getGatewayUrl(String accessToken, String account)
+            throws FireboltException {
+        String url = String.format(URL, account);
+        try {
+            return getResource(url, accessToken, GatewayUrlResponse.class);
+        } catch (FireboltException e) {
+            throw e;
+        } catch (Exception e) {
+            throw new FireboltException(String.format("Failed to get gateway url for account %s", account), e);
+        }
+    }
+
+}
diff --git a/src/main/java/com/firebolt/jdbc/client/gateway/GatewayUrlResponse.java b/src/main/java/com/firebolt/jdbc/client/gateway/GatewayUrlResponse.java
new file mode 100644
index 000000000..986e7f614
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/client/gateway/GatewayUrlResponse.java
@@ -0,0 +1,15 @@
+package com.firebolt.jdbc.client.gateway;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Value;
+
+
+@Value
+@AllArgsConstructor
+@Builder
+public class GatewayUrlResponse {
+    @JsonProperty("engineUrl")
+    String engineUrl;
+}
diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index 8afa08e8a..7e6d8563f 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -36,6 +36,9 @@ public class StatementClientImpl extends FireboltClient implements StatementClie
 
 	private static final String TAB_SEPARATED_WITH_NAMES_AND_TYPES_FORMAT = "TabSeparatedWithNamesAndTypes";
 
+	private static final List<String> URI_QUERY_SEGMENTS = Arrays.asList("dynamic","query");
+
+
 	private final BiPredicate<Call, String> isCallWithId = (call, id) -> call.request().tag() instanceof String
 			&& StringUtils.equals((String) call.request().tag(), id);
 
@@ -173,7 +176,7 @@ public boolean isStatementRunning(String statementId) {
 	}
 
 	private URI buildQueryUri(FireboltProperties fireboltProperties, Map<String, String> parameters) {
-		return buildURI(fireboltProperties, parameters, Collections.emptyList());
+		return buildURI(fireboltProperties, parameters, PropertyUtil.isLocalDb(fireboltProperties) ? Collections.emptyList() : URI_QUERY_SEGMENTS);
 	}
 
 	private URI buildCancelUri(FireboltProperties fireboltProperties, String id) {
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index 400b230e4..4493d3f54 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -1,8 +1,10 @@
 package com.firebolt.jdbc.connection;
 
+import static com.firebolt.jdbc.connection.settings.FireboltProperties.SYSTEM_ENGINE_NAME;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
 
 import java.io.IOException;
+import java.net.URI;
 import java.security.KeyManagementException;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
@@ -11,6 +13,9 @@
 import java.util.*;
 import java.util.concurrent.Executor;
 
+import com.firebolt.jdbc.client.gateway.FireboltGatewayUrlClient;
+import com.firebolt.jdbc.service.FireboltEngineService;
+import com.firebolt.jdbc.service.FireboltGatewayUrlService;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 
@@ -20,7 +25,6 @@
 import com.firebolt.jdbc.annotation.NotImplemented;
 import com.firebolt.jdbc.client.FireboltObjectMapper;
 import com.firebolt.jdbc.client.HttpClientConfig;
-import com.firebolt.jdbc.client.account.FireboltAccountClient;
 import com.firebolt.jdbc.client.authentication.FireboltAuthenticationClient;
 import com.firebolt.jdbc.client.query.StatementClientImpl;
 import com.firebolt.jdbc.connection.settings.FireboltProperties;
@@ -31,7 +35,6 @@
 import com.firebolt.jdbc.metadata.FireboltDatabaseMetadata;
 import com.firebolt.jdbc.metadata.FireboltSystemEngineDatabaseMetadata;
 import com.firebolt.jdbc.service.FireboltAuthenticationService;
-import com.firebolt.jdbc.service.FireboltEngineService;
 import com.firebolt.jdbc.service.FireboltStatementService;
 import com.firebolt.jdbc.statement.FireboltStatement;
 import com.firebolt.jdbc.statement.preparedstatement.FireboltPreparedStatement;
@@ -44,47 +47,52 @@
 public class FireboltConnection implements Connection {
 
 	private final FireboltAuthenticationService fireboltAuthenticationService;
-	private final FireboltEngineService fireboltEngineService;
 	private final FireboltStatementService fireboltStatementService;
+
+	private final FireboltEngineService fireboltEngineService;
+
+	private final FireboltGatewayUrlService fireboltGatewayUrlService;
 	private final String httpConnectionUrl;
 	private final List<FireboltStatement> statements;
 	private final int connectionTimeout;
 	private final boolean systemEngine;
 	private boolean closed = true;
 	private FireboltProperties sessionProperties;
+	private FireboltProperties internalSystemEngineProperties;
 	private int networkTimeout;
 
 	//Properties that are used at the beginning of the connection for authentication
 	private final FireboltProperties loginProperties;
 
 	public FireboltConnection(@NonNull String url, Properties connectionSettings,
-			FireboltAuthenticationService fireboltAuthenticationService, FireboltEngineService fireboltEngineService,
-			FireboltStatementService fireboltStatementService) throws FireboltException {
+			FireboltAuthenticationService fireboltAuthenticationService,
+			FireboltGatewayUrlService fireboltGatewayUrlService, FireboltStatementService fireboltStatementService, FireboltEngineService fireboltEngineService) throws FireboltException {
 		this.fireboltAuthenticationService = fireboltAuthenticationService;
-		this.fireboltEngineService = fireboltEngineService;
-		loginProperties = this.extractFireboltProperties(url, connectionSettings);
+		this.fireboltGatewayUrlService = fireboltGatewayUrlService;
+		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
 		this.httpConnectionUrl = getHttpConnectionUrl(loginProperties);
 		this.fireboltStatementService = fireboltStatementService;
 		this.statements = new ArrayList<>();
 		this.connectionTimeout = loginProperties.getConnectionTimeoutMillis();
 		this.networkTimeout = loginProperties.getSocketTimeoutMillis();
 		this.systemEngine = loginProperties.isSystemEngine();
+		this.fireboltEngineService = fireboltEngineService;
 		this.connect();
 	}
 
 	@ExcludeFromJacocoGeneratedReport
 	public FireboltConnection(@NonNull String url, Properties connectionSettings) throws FireboltException {
 		ObjectMapper objectMapper = FireboltObjectMapper.getInstance();
-		loginProperties = this.extractFireboltProperties(url, connectionSettings);
+		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
 		this.httpConnectionUrl = getHttpConnectionUrl(loginProperties);
 		OkHttpClient httpClient = getHttpClient(loginProperties);
 		this.systemEngine = loginProperties.isSystemEngine();
+		this.fireboltGatewayUrlService = new FireboltGatewayUrlService(new FireboltGatewayUrlClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
 		this.fireboltAuthenticationService = new FireboltAuthenticationService(
 				new FireboltAuthenticationClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
-		this.fireboltEngineService = new FireboltEngineService(
-				new FireboltAccountClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
+		this.fireboltEngineService = new FireboltEngineService(this);
 		this.fireboltStatementService = new FireboltStatementService(
-				new StatementClientImpl(httpClient, this, objectMapper, loginProperties.getUserDrivers(), loginProperties.getUserClients()), systemEngine);
+				new StatementClientImpl(httpClient, this, objectMapper, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
 		this.statements = new ArrayList<>();
 		this.connectionTimeout = loginProperties.getConnectionTimeoutMillis();
 		this.networkTimeout = loginProperties.getSocketTimeoutMillis();
@@ -103,17 +111,41 @@ private static OkHttpClient getHttpClient(FireboltProperties fireboltProperties)
 
 	private void connect() throws FireboltException {
 		String accessToken = this.getAccessToken(loginProperties).orElse(StringUtils.EMPTY);
+		closed = false;
 		if (!PropertyUtil.isLocalDb(loginProperties)) {
-			String endpoint = fireboltEngineService.getEngine(httpConnectionUrl, loginProperties, accessToken)
-					.getEndpoint();
-			this.sessionProperties = loginProperties.toBuilder().host(endpoint).build();
+			internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, this.loginProperties.getAccount());
+			if (!this.loginProperties.isSystemEngine()) {
+				sessionProperties = getSessionPropertiesForNonSystemEngine();
+			} else {
+				//When using system engine, the system engine properties are the same as the session properties
+				sessionProperties = internalSystemEngineProperties.toBuilder().build();
+			}
 		} else {
-			this.sessionProperties = loginProperties;
+			//When running packdb locally, the login properties are the session properties
+			sessionProperties = loginProperties;
 		}
-		closed = false;
 		log.debug("Connection opened");
 	}
 
+	private FireboltProperties getSessionPropertiesForNonSystemEngine() {
+
+/*		This is currently not supported
+		Engine engine = fireboltEngineService.getEngine(this.loginProperties.getEngine(), this.loginProperties.getDatabase());
+		return loginProperties.toBuilder().host(engine.getEndpoint()).engine(engine.getName()).build();*/
+		//temporary workaround
+		return internalSystemEngineProperties.toBuilder().build();
+	}
+
+	private FireboltProperties createInternalSystemEngineProperties(String accessToken, String account) throws FireboltException {
+		String systemEngineEndpoint = fireboltGatewayUrlService.getUrl(accessToken, account);
+		return this.loginProperties
+				.toBuilder()
+				.systemEngine(true)
+				.engine(SYSTEM_ENGINE_NAME)
+				.compress(false)
+				.host(URI.create(systemEngineEndpoint).getHost()).database(null).build();
+	}
+
 	public void removeExpiredTokens() throws FireboltException {
 		fireboltAuthenticationService.removeConnectionTokens(httpConnectionUrl, loginProperties);
 	}
@@ -147,6 +179,10 @@ public Statement createStatement(FireboltProperties fireboltProperties) throws S
 		return fireboltStatement;
 	}
 
+	public Statement createSystemEngineStatementStatement() throws SQLException {
+		return createStatement(internalSystemEngineProperties);
+	}
+
 	private void addStatement(FireboltStatement statement) throws SQLException {
 		synchronized (statements) {
 			this.validateConnectionIsNotClose();
@@ -194,9 +230,8 @@ public void setCatalog(String catalog) throws SQLException {
 		// no-op as catalogs are not supported
 	}
 
-	public String getEngine() throws SQLException {
-		this.validateConnectionIsNotClose();
-		return fireboltEngineService.getEngineNameFromHost(this.getSessionProperties().getHost());
+	public String getEngine()  {
+		return this.getSessionProperties().getEngine();
 	}
 
 	@Override
@@ -266,7 +301,7 @@ public void close() {
 	}
 
 	private FireboltProperties extractFireboltProperties(String jdbcUri, Properties connectionProperties) {
-		Properties propertiesFromUrl = FireboltJdbcUrlUtil.extractProperties(jdbcUri);
+		Properties propertiesFromUrl = UrlUtil.extractProperties(jdbcUri);
 		return FireboltProperties.of(propertiesFromUrl, connectionProperties);
 	}
 
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtil.java b/src/main/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtil.java
deleted file mode 100644
index b509c8d67..000000000
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtil.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.firebolt.jdbc.connection;
-
-import java.net.URI;
-import java.util.Optional;
-import java.util.Properties;
-
-import org.apache.commons.lang3.StringUtils;
-
-import com.firebolt.jdbc.connection.settings.FireboltSessionProperty;
-
-import lombok.CustomLog;
-import lombok.experimental.UtilityClass;
-
-@CustomLog
-@UtilityClass
-public class FireboltJdbcUrlUtil {
-
-	public static final String JDBC_PREFIX = "jdbc:";
-
-	public static Properties extractProperties(String jdbcUrl) {
-		URI uri = extractUriFromJdbcUrl(jdbcUrl);
-		return parseUriQueryPart(uri);
-	}
-
-	private URI extractUriFromJdbcUrl(String jdbcConnectionString) {
-		String cleanURI = StringUtils.replace(jdbcConnectionString, JDBC_PREFIX, "");
-		return URI.create(cleanURI);
-	}
-
-	private static Properties parseUriQueryPart(URI uri) {
-		Properties uriProperties = new Properties();
-		String query = uri.getQuery();
-		if (StringUtils.isNotBlank(query)) {
-			String[] queryKeyValues = query.split("&");
-			for (String keyValue : queryKeyValues) {
-				String[] keyValueTokens = keyValue.split("=");
-				if (keyValueTokens.length == 2) {
-					uriProperties.put(keyValueTokens[0], keyValueTokens[1]);
-				} else {
-					log.warn("Cannot parse key-pair: {}", keyValue);
-				}
-			}
-		}
-		Optional.ofNullable(uri.getPath())
-				.ifPresent(path -> uriProperties.put(FireboltSessionProperty.PATH.getKey(), path));
-		Optional.ofNullable(uri.getHost())
-				.ifPresent(host -> uriProperties.put(FireboltSessionProperty.HOST.getKey(), host));
-		Optional.of(uri.getPort()).filter(p -> !p.equals(-1))
-				.ifPresent(port -> uriProperties.put(FireboltSessionProperty.PORT.getKey(), String.valueOf(port)));
-		return uriProperties;
-	}
-}
diff --git a/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java b/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
new file mode 100644
index 000000000..e666dc77d
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
@@ -0,0 +1,44 @@
+package com.firebolt.jdbc.connection;
+
+import com.firebolt.jdbc.connection.settings.FireboltSessionProperty;
+import lombok.CustomLog;
+import lombok.experimental.UtilityClass;
+import org.apache.commons.lang3.StringUtils;
+
+import java.net.URI;
+import java.util.Optional;
+import java.util.Properties;
+
+@CustomLog
+@UtilityClass
+public class UrlUtil {
+
+    public static final String JDBC_PREFIX = "jdbc:firebolt:";
+
+    public static Properties extractProperties(String jdbcUrl) {
+        return parseUriQueryPart(jdbcUrl);
+    }
+
+
+    private static Properties parseUriQueryPart(String jdbcConnectionString) {
+        String cleanURI = StringUtils.replace(jdbcConnectionString, JDBC_PREFIX, "");
+        URI uri = URI.create(cleanURI);
+        Properties uriProperties = new Properties();
+        String query = uri.getQuery();
+        if (StringUtils.isNotBlank(query)) {
+            String[] queryKeyValues = query.split("&");
+            for (String keyValue : queryKeyValues) {
+                String[] keyValueTokens = keyValue.split("=");
+                if (keyValueTokens.length == 2) {
+                    uriProperties.put(keyValueTokens[0], keyValueTokens[1]);
+                } else {
+                    log.warn("Cannot parse key-pair: {}", keyValue);
+                }
+            }
+        }
+        Optional.ofNullable(uri.getPath()).map(p -> !StringUtils.isEmpty(p) ? StringUtils.removeEnd(p, "/") : p).ifPresent(path -> uriProperties.put(FireboltSessionProperty.PATH.getKey(), path));
+        Optional.of(uri.getPort()).filter(p -> !p.equals(-1))
+                .ifPresent(port -> uriProperties.put(FireboltSessionProperty.PORT.getKey(), String.valueOf(port)));
+        return uriProperties;
+    }
+}
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index 29b762f69..7966e2a8a 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -18,10 +18,10 @@
 @CustomLog
 public class FireboltProperties {
 
-	private static final Pattern DB_PATH_PATTERN = Pattern.compile("/([a-zA-Z0-9_*\\-]+)");
+	public static final String SYSTEM_ENGINE_NAME = "system";
+	private static final Pattern DB_PATH_PATTERN = Pattern.compile("([a-zA-Z0-9_*\\-]+)");
 	private static final int FIREBOLT_SSL_PROXY_PORT = 443;
 	private static final int FIREBOLT_NO_SSL_PROXY_PORT = 9090;
-	private static final String SYSTEM_ENGINE_NAME = "system";
 
 	private static final Set<String> sessionPropertyKeys = Arrays.stream(FireboltSessionProperty.values())
 			.map(property -> {
@@ -55,6 +55,8 @@ public class FireboltProperties {
 	Integer tcpKeepInterval;
 	boolean logResultSet;
 	boolean systemEngine;
+	String organization;
+	String environment;
 	String userDrivers;
 	String userClients;
 
@@ -69,7 +71,8 @@ public static FireboltProperties of(Properties... properties) {
 		String user = getSetting(mergedProperties, FireboltSessionProperty.USER);
 		String password = getSetting(mergedProperties, FireboltSessionProperty.PASSWORD);
 		String path = getSetting(mergedProperties, FireboltSessionProperty.PATH);
-		String engine = getSetting(mergedProperties, FireboltSessionProperty.ENGINE);
+		String database = getDatabase(mergedProperties, path);
+		String engine = getEngine(mergedProperties, database);
 		boolean isSystemEngine = isSystemEngine(engine);
 		boolean compress = ((Boolean) getSetting(mergedProperties, FireboltSessionProperty.COMPRESS))
 				&& !isSystemEngine;
@@ -84,12 +87,13 @@ public static FireboltProperties of(Properties... properties) {
 		int tcpKeepIdle = getSetting(mergedProperties, FireboltSessionProperty.TCP_KEEP_IDLE);
 		int tcpKeepCount = getSetting(mergedProperties, FireboltSessionProperty.TCP_KEEP_COUNT);
 		boolean logResultSet = getSetting(mergedProperties, FireboltSessionProperty.LOG_RESULT_SET);
+		String environment = getSetting(mergedProperties, FireboltSessionProperty.ENVIRONMENT);
 		String driverVersions = getSetting(mergedProperties, FireboltSessionProperty.USER_DRIVERS);
 		String clientVersions = getSetting(mergedProperties, FireboltSessionProperty.USER_CLIENTS);
 
-		String host = getHost(mergedProperties);
+		String host = getHost(environment, mergedProperties);
 		Integer port = getPort(mergedProperties, ssl);
-		String database = getDatabase(mergedProperties, path);
+
 		Map<String, String> additionalProperties = getFireboltCustomProperties(mergedProperties);
 
 		return FireboltProperties.builder().ssl(ssl).sslCertificatePath(sslRootCertificate).sslMode(sslMode).path(path)
@@ -99,15 +103,25 @@ public static FireboltProperties of(Properties... properties) {
 				.bufferSize(bufferSize).socketTimeoutMillis(socketTimeout).connectionTimeoutMillis(connectionTimeout)
 				.tcpKeepInterval(tcpKeepInterval).tcpKeepCount(tcpKeepCount).tcpKeepIdle(tcpKeepIdle)
 				.logResultSet(logResultSet).systemEngine(isSystemEngine)
+				.environment(environment)
 				.userDrivers(driverVersions)
 				.userClients(clientVersions)
 				.build();
 	}
 
-	private static String getHost(Properties properties) {
+	private static String getEngine(Properties mergedProperties, String database) {
+		String engine = getSetting(mergedProperties, FireboltSessionProperty.ENGINE);
+		if (StringUtils.isEmpty(engine) && StringUtils.isEmpty(database)) {
+			return SYSTEM_ENGINE_NAME;
+		} else {
+			return engine;
+		}
+	}
+
+	private static String getHost(String environment, Properties properties ) {
 		String host = getSetting(properties, FireboltSessionProperty.HOST);
 		if (StringUtils.isEmpty(host)) {
-			throw new IllegalArgumentException("Invalid host: The host is missing or empty");
+			return String.format("api.%s.firebolt.io", environment);
 		} else {
 			return host;
 		}
@@ -125,8 +139,8 @@ private static Integer getPort(Properties properties, boolean ssl) {
 	private static String getDatabase(Properties properties, String path) throws IllegalArgumentException {
 		String database = getSetting(properties, FireboltSessionProperty.DATABASE);
 		if (StringUtils.isEmpty(database)) {
-			if ("/".equals(path)) {
-				throw new IllegalArgumentException("A database must be provided");
+			if ("/".equals(path) || StringUtils.isEmpty(path)) {
+				return null;
 			} else {
 				Matcher m = DB_PATH_PATTERN.matcher(path);
 				if (m.matches()) {
@@ -201,4 +215,9 @@ public void addProperty(@NonNull String key, String value) {
 	public void addProperty(Pair<String, String> property) {
 		this.addProperty(property.getLeft(), property.getRight());
 	}
+
+	public static FireboltProperties toSystemEngineProperties(FireboltProperties properties) {
+		return properties.toBuilder().additionalProperties(new HashMap<>(properties.getAdditionalProperties())).build();
+	}
+
 }
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
index 162da19fb..5373bb9d0 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
@@ -10,7 +10,7 @@
 
 @Getter
 public enum FireboltSessionProperty {
-	PATH("path", "/", String.class, "Path component of the URI"),
+	PATH("path", "", String.class, "Path component of the URI"),
 	BUFFER_SIZE("buffer_size", 65536, Integer.class, "The buffer used to create the ResultSet in bytes"),
 	SSL("ssl", true, Boolean.class, "Enable SSL/TLS for the connection"),
 	SSL_CERTIFICATE_PATH("ssl_certificate_path", "", String.class, "SSL/TLS root certificate", "sslrootcert"),
@@ -49,12 +49,12 @@ public enum FireboltSessionProperty {
 	HOST("host", null, String.class, "Firebolt host - null by default"),
 	PORT("port", null, Integer.class, "Firebolt port - null by default"),
 	ENGINE("engine", null, String.class, "engine - null by default", "engine_name"),
-	ACCOUNT("account", null, String.class, "account - null by default"),
+	ACCOUNT("account", "firebolt", String.class, "account - null by default"),
 	LOG_RESULT_SET("log_result_set", false, Boolean.class,
 			"When set to true, the result of the queries executed are logged with the log level INFO. This has a negative performance impact and should be enabled only for debugging purposes"),
 	USER_DRIVERS("user_drivers", null, String.class, "user drivers"),
 	USER_CLIENTS("user_clients", null, String.class, "user clients"),
-
+	ENVIRONMENT("environment", "app", String.class, "Firebolt environment", "env"),
 	// We keep all the deprecated properties to ensure backward compatibility - but
 	// they do not have any effect.
 	@Deprecated
diff --git a/src/main/java/com/firebolt/jdbc/metadata/MetadataUtil.java b/src/main/java/com/firebolt/jdbc/metadata/MetadataUtil.java
index a56685f7a..31b16cfb6 100644
--- a/src/main/java/com/firebolt/jdbc/metadata/MetadataUtil.java
+++ b/src/main/java/com/firebolt/jdbc/metadata/MetadataUtil.java
@@ -1,13 +1,12 @@
 package com.firebolt.jdbc.metadata;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 
-import com.firebolt.jdbc.Query;
+import org.apache.commons.lang3.StringUtils;
 
+import lombok.Builder;
 import lombok.NonNull;
+import lombok.Value;
 import lombok.experimental.UtilityClass;
 
 @UtilityClass
@@ -102,4 +101,61 @@ public static String getDatabaseVersionQuery(String engine) {
 				.conditions(Collections.singletonList(String.format("engine_name iLIKE '%s%%'", engine))).build()
 				.toSql();
 	}
+
+	/**
+	 * Represents a SQL query that can be sent to Firebolt to receive metadata info
+	 */
+	@Builder
+	@Value
+	public static class Query {
+		String select;
+		String from;
+		String innerJoin;
+		String orderBy;
+		List<String> conditions;
+
+		/**
+		 * Parse the object to a SQL query that can be sent to Firebolt
+		 *
+		 * @return SQL query that can be sent to Firebolt
+		 */
+		public String toSql() {
+			StringBuilder query = new StringBuilder();
+			if (StringUtils.isBlank(select)) {
+				throw new IllegalStateException("Cannot create query: SELECT cannot be blank");
+			}
+			if (StringUtils.isBlank(from)) {
+				throw new IllegalStateException("Cannot create query: FROM cannot be blank");
+			}
+
+			query.append("SELECT ").append(select);
+			query.append(" FROM ").append(from);
+			if (StringUtils.isNotBlank(innerJoin)) {
+				query.append(" JOIN ").append(innerJoin);
+			}
+			query.append(getConditionsPart());
+			if (StringUtils.isNotBlank(orderBy)) {
+				query.append(" order by ").append(orderBy);
+			}
+			return query.toString();
+		}
+
+		private String getConditionsPart() {
+			StringBuilder agg = new StringBuilder();
+			Iterator<String> iter = conditions.iterator();
+			if (iter.hasNext()) {
+				agg.append(" WHERE ");
+			}
+			if (iter.hasNext()) {
+				String entry = iter.next();
+				agg.append(entry);
+			}
+			while (iter.hasNext()) {
+				String entry = iter.next();
+				agg.append(" AND ").append(entry);
+			}
+			return agg.toString();
+		}
+	}
+
 }
diff --git a/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java b/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java
index 37edae5eb..8959aa2e4 100644
--- a/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java
+++ b/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java
@@ -11,12 +11,12 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+import com.firebolt.jdbc.QueryResult;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.commons.text.StringEscapeUtils;
 
 import com.firebolt.jdbc.util.LoggerUtil;
-import com.firebolt.jdbc.QueryResult;
 import com.firebolt.jdbc.annotation.ExcludeFromJacocoGeneratedReport;
 import com.firebolt.jdbc.annotation.NotImplemented;
 import com.firebolt.jdbc.exception.FireboltException;
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java b/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
index 9c393d287..1762fba39 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
@@ -41,7 +41,7 @@ public FireboltConnectionTokens getConnectionTokens(String host, FireboltPropert
 					return foundToken;
 				} else {
 					FireboltConnectionTokens fireboltConnectionTokens = fireboltAuthenticationClient
-							.postConnectionTokens(host, loginProperties.getUser(), loginProperties.getPassword());
+							.postConnectionTokens(host, loginProperties.getUser(), loginProperties.getPassword(), loginProperties.getEnvironment());
 					long durationInSeconds = getCachingDurationInSeconds(
 							fireboltConnectionTokens.getExpiresInSeconds());
 					tokensMap.put(connectionParams, fireboltConnectionTokens, ExpirationPolicy.CREATED,
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
index 3ebac44b2..c7f59f3df 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
@@ -1,20 +1,16 @@
 package com.firebolt.jdbc.service;
 
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashSet;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.Optional;
-import java.util.Set;
+
+import javax.annotation.Nullable;
 
 import org.apache.commons.lang3.StringUtils;
 
-import com.firebolt.jdbc.client.account.FireboltAccountClient;
-import com.firebolt.jdbc.client.account.response.FireboltAccountResponse;
-import com.firebolt.jdbc.client.account.response.FireboltDefaultDatabaseEngineResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineIdResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineResponse;
 import com.firebolt.jdbc.connection.Engine;
-import com.firebolt.jdbc.connection.settings.FireboltProperties;
+import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
 
 import lombok.CustomLog;
@@ -23,95 +19,78 @@
 @RequiredArgsConstructor
 @CustomLog
 public class FireboltEngineService {
-	private static final Set<String> ENGINE_NOT_READY_STATUSES = new HashSet<>(
-			Arrays.asList("ENGINE_STATUS_PROVISIONING_STARTED", "ENGINE_STATUS_PROVISIONING_PENDING",
-					"ENGINE_STATUS_PROVISIONING_FINISHED", "ENGINE_STATUS_RUNNING_REVISION_STARTING"));
-	private static final String ERROR_NO_ENGINE_ATTACHED = "There is no Firebolt engine running on %s attached to the database %s. To connect first make sure there is a running engine and then try again.";
-	private static final String ERROR_NO_ENGINE_WITH_NAME = "There is no Firebolt engine running on %s with the name %s. To connect first make sure there is a running engine and then try again.";
-	private final FireboltAccountClient fireboltAccountClient;
-
-	/**
-	 * Returns the engine
-	 *
-	 * @param connectionUrl   the connection url
-	 * @param loginProperties properties to login
-	 * @param accessToken     the access token
-	 * @return the engine
-	 */
-	public Engine getEngine(String connectionUrl, FireboltProperties loginProperties, String accessToken)
-			throws FireboltException {
-		String accountId = null;
-		Engine engine;
-		try {
-			if (StringUtils.isNotEmpty(loginProperties.getAccount())) {
-				accountId = getAccountId(connectionUrl, loginProperties.getAccount(), accessToken).orElse(null);
-			}
-			if (StringUtils.isEmpty(loginProperties.getEngine())) {
-				engine = getDefaultEngine(connectionUrl, accountId, loginProperties.getDatabase(), accessToken);
-			} else {
-				engine = getEngineWithName(connectionUrl, accountId, loginProperties.getEngine(), accessToken);
-			}
-		} catch (FireboltException e) {
-			throw e;
-		} catch (Exception e) {
-			throw new FireboltException("Failed to get engine", e);
-		}
-		validateEngineIsNotStarting(engine);
-		return engine;
-	}
+    private static final String ENGINE_URL = "engine_url";
+    private static final String ENGINE_NAME = "engine_name";
+    private static final String STATUS_FIELD_NAME = "status";
+    private static final String DEFAULT_ENGINE_QUERY = "SELECT engs.engine_url, engs.status, engs.engine_name\n" +
+            "FROM information_schema.databases AS dbs\n" +
+            "INNER JOIN information_schema.engines AS engs\n" +
+            "ON engs.attached_to = dbs.database_name\n" +
+            "AND engs.engine_name = NULLIF(SPLIT_PART(ARRAY_FIRST(\n" +
+            "        eng_name -> eng_name LIKE '%%(default)',\n" +
+            "        SPLIT(',', attached_engines)\n" +
+            "    ), ' ', 1), '')\n" +
+            "WHERE database_name = '%s'";
+    private static final String ENGINE_QUERY = "SELECT engine_url, attached_to, status FROM information_schema.engines \n" +
+            "WHERE engine_name='%s'";
+    private static final String RUNNING_STATUS = "running";
+    private final FireboltConnection fireboltConnection;
 
-	private Engine getEngineWithName(String connectionUrl, String accountId, String engineName, String accessToken)
-			throws FireboltException, IOException {
-		FireboltEngineIdResponse response = fireboltAccountClient.getEngineId(connectionUrl, accountId, engineName,
-				accessToken);
-		String engineID = Optional.ofNullable(response).map(FireboltEngineIdResponse::getEngine)
-				.map(FireboltEngineIdResponse.Engine::getEngineId).orElseThrow(() -> new FireboltException(
-						"Failed to extract engine id field from the server response: the response from the server is invalid."));
-		FireboltEngineResponse fireboltEngineResponse = fireboltAccountClient.getEngine(connectionUrl, accountId,
-				engineName, engineID, accessToken);
+    /**
+     * Extracts the engine name from host
+     *
+     * @param engineHost engine host
+     * @return the engine name
+     */
+    public String getEngineNameByHost(String engineHost) throws FireboltException {
+        return Optional.ofNullable(engineHost).filter(host -> host.contains(".")).map(host -> host.split("\\.")[0])
+                .map(host -> host.replace("-", "_")).orElseThrow(() -> new FireboltException(
+                        String.format("Could not establish the engine from the host: %s", engineHost)));
+    }
 
-		return Optional.ofNullable(fireboltEngineResponse).map(FireboltEngineResponse::getEngine)
-				.filter(e -> StringUtils.isNotEmpty(e.getEndpoint()))
-				.map(e -> Engine.builder().endpoint(e.getEndpoint()).id(engineID).status(e.getCurrentStatus())
-						.name(engineName).build())
-				.orElseThrow(() -> new FireboltException(
-						String.format(ERROR_NO_ENGINE_WITH_NAME, connectionUrl, engineName)));
-	}
+    public Engine getEngine(@Nullable String name, @Nullable String database) throws FireboltException {
+        if (StringUtils.isEmpty(name)) {
+            return this.getDefaultEngine(database);
+        } else {
+            return Engine.builder().name(name).endpoint(getEngineEndpoint(name)).build();
+        }
+    }
 
-	private Engine getDefaultEngine(String connectionUrl, String accountId, String database, String accessToken)
-			throws FireboltException, IOException {
-		FireboltDefaultDatabaseEngineResponse defaultEngine = fireboltAccountClient
-				.getDefaultEngineByDatabaseName(connectionUrl, accountId, database, accessToken);
-		return Optional.ofNullable(defaultEngine).map(FireboltDefaultDatabaseEngineResponse::getEngineUrl)
-				.map(url -> Engine.builder().endpoint(url).build()).orElseThrow(
-						() -> new FireboltException(String.format(ERROR_NO_ENGINE_ATTACHED, connectionUrl, database)));
-	}
+    private Engine getDefaultEngine(String database) throws FireboltException {
+        try (Statement statement = this.fireboltConnection.createSystemEngineStatementStatement();
+             ResultSet resultSet = statement.executeQuery(String.format(DEFAULT_ENGINE_QUERY, database))) {
+            if (!resultSet.next()) {
+                throw new FireboltException(String.format("The default engine for the database %s could not be found", database));
+            }
+            String status = resultSet.getString(STATUS_FIELD_NAME);
+            if (isEngineNotRunning(status)) {
+                throw new FireboltException(String.format("The default engine for the database %s is not running. Status: %s", database, status));
+            }
+            return Engine.builder().endpoint(resultSet.getString(ENGINE_URL)).name(resultSet.getString(ENGINE_NAME)).build();
+        } catch (SQLException sqlException) {
+            throw new FireboltException(String.format("Could not get default engine url for database %s", database), sqlException);
+        }
+    }
 
-	private Optional<String> getAccountId(String connectionUrl, String account, String accessToken)
-			throws FireboltException, IOException {
-		FireboltAccountResponse fireboltAccountResponse = fireboltAccountClient.getAccount(connectionUrl, account,
-				accessToken);
-		return Optional.ofNullable(fireboltAccountResponse).map(FireboltAccountResponse::getAccountId);
-	}
+    private String getEngineEndpoint(String engine) throws FireboltException {
+        try (Statement statement = this.fireboltConnection.createSystemEngineStatementStatement();
+             ResultSet resultSet = statement.executeQuery(String.format(ENGINE_QUERY, engine))) {
+            if (!resultSet.next()) {
+                throw new FireboltException(String.format("The engine with the name %s could not be found", engine));
+            }
+            String status = resultSet.getString(STATUS_FIELD_NAME);
+            if (isEngineNotRunning(status)) {
+                throw new FireboltException(String.format("The engine with the name %s is not running. Status: %s", engine, status));
+            }
+            return resultSet.getString(ENGINE_URL);
+        } catch (SQLException sqlException) {
+            throw new FireboltException(String.format("Could not get engine url for engine %s", engine), sqlException);
+        }
+    }
 
-	private void validateEngineIsNotStarting(Engine engine) throws FireboltException {
-		if (StringUtils.isNotEmpty(engine.getId()) && StringUtils.isNotEmpty(engine.getStatus())
-				&& ENGINE_NOT_READY_STATUSES.contains(engine.getStatus())) {
-			throw new FireboltException(String.format(
-					"The engine %s is currently starting. Please wait until the engine is on and then execute the query again.", engine.getName()));
-		}
-	}
+    private boolean isEngineNotRunning(String status) {
+        return !StringUtils.equalsIgnoreCase(RUNNING_STATUS, status);
+    }
 
-	/**
-	 * Extracts the engine name from host
-	 *
-	 * @param engineHost engine host
-	 * @return the engine name
-	 */
-	public String getEngineNameFromHost(String engineHost) throws FireboltException {
-		return Optional.ofNullable(engineHost).filter(host -> host.contains(".")).map(host -> host.split("\\.")[0])
-				.map(host -> host.replace("-", "_")).orElseThrow(() -> new FireboltException(
-						String.format("Could not establish the engine from the host: %s", engineHost)));
-	}
 
 }
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java b/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
new file mode 100644
index 000000000..0b91d0b87
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
@@ -0,0 +1,15 @@
+package com.firebolt.jdbc.service;
+
+import com.firebolt.jdbc.client.gateway.FireboltGatewayUrlClient;
+import com.firebolt.jdbc.exception.FireboltException;
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class FireboltGatewayUrlService {
+
+    private final FireboltGatewayUrlClient fireboltGatewayUrlClient;
+
+    public String getUrl(String accessToken, String account) throws FireboltException {
+        return fireboltGatewayUrlClient.getGatewayUrl(accessToken, account).getEngineUrl();
+    }
+}
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltStatementService.java b/src/main/java/com/firebolt/jdbc/service/FireboltStatementService.java
index 5a32aaebf..ad8e8acf4 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltStatementService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltStatementService.java
@@ -28,7 +28,6 @@ public class FireboltStatementService {
 
 	private static final String UNKNOWN_TABLE_NAME = "unknown";
 	private final StatementClient statementClient;
-	private final boolean systemEngine;
 
 	/**
 	 * Executes statement
@@ -38,12 +37,12 @@ public class FireboltStatementService {
 	 * @param queryTimeout         query timeout
 	 * @param maxRows              max rows
 	 * @param standardSql          indicates if standard sql should be used
+	 * @param systemEngine         indicates if system engine is used
 	 * @param statement           the statement
 	 * @return an InputStream with the result
 	 */
 	public Optional<ResultSet> execute(StatementInfoWrapper statementInfoWrapper,
-									   FireboltProperties properties, int queryTimeout, int maxRows, boolean standardSql,
-									   FireboltStatement statement)
+									   FireboltProperties properties, int queryTimeout, int maxRows, boolean standardSql, boolean systemEngine, FireboltStatement statement)
 			throws SQLException {
 		InputStream is = statementClient.executeSqlStatement(statementInfoWrapper, properties, systemEngine, queryTimeout,
 				maxRows, standardSql);
@@ -60,7 +59,7 @@ public Optional<ResultSet> execute(StatementInfoWrapper statementInfoWrapper,
 
 	public void abortStatement(@NonNull String statementId, @NonNull FireboltProperties properties)
 			throws FireboltException {
-		if (systemEngine) {
+		if (properties.isSystemEngine()) {
 			throw new FireboltException("Cannot cancel a statement using a system engine", INVALID_REQUEST);
 		} else {
 			statementClient.abortStatement(statementId, properties);
diff --git a/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java b/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java
index 73b4306cd..aa3c38dc8 100644
--- a/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java
+++ b/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java
@@ -109,7 +109,7 @@ private Optional<ResultSet> execute(StatementInfoWrapper statementInfoWrapper, b
 					log.debug("The property from the query {} was stored", runningStatementId);
 				} else {
 					Optional<ResultSet> currentRs = statementService.execute(statementInfoWrapper,
-							this.sessionProperties, this.queryTimeout, this.maxRows, isStandardSql, this);
+							this.sessionProperties, this.queryTimeout, this.maxRows, isStandardSql, sessionProperties.isSystemEngine(), this);
 					if (currentRs.isPresent()) {
 						resultSet = currentRs.get();
 						currentUpdateCount = -1; // Always -1 when returning a ResultSet
diff --git a/src/main/java/com/firebolt/jdbc/util/PropertyUtil.java b/src/main/java/com/firebolt/jdbc/util/PropertyUtil.java
index 7b460cfb0..3be9bc77b 100644
--- a/src/main/java/com/firebolt/jdbc/util/PropertyUtil.java
+++ b/src/main/java/com/firebolt/jdbc/util/PropertyUtil.java
@@ -7,9 +7,9 @@
 import java.util.Properties;
 import java.util.stream.Collectors;
 
+import com.firebolt.jdbc.connection.UrlUtil;
 import org.apache.commons.lang3.StringUtils;
 
-import com.firebolt.jdbc.connection.FireboltJdbcUrlUtil;
 import com.firebolt.jdbc.connection.settings.FireboltProperties;
 import com.firebolt.jdbc.connection.settings.FireboltSessionProperty;
 
@@ -31,7 +31,7 @@ public class PropertyUtil {
 	 */
 	public DriverPropertyInfo[] getPropertyInfo(String url, Properties properties) {
 		try {
-			Properties propertiesFromUrl = FireboltJdbcUrlUtil.extractProperties(url);
+			Properties propertiesFromUrl = UrlUtil.extractProperties(url);
 			for (Object key : propertiesFromUrl.keySet()) {
 				properties.put(key, propertiesFromUrl.get(key.toString()));
 			}
diff --git a/src/test/java/com/firebolt/jdbc/RawStatementTest.java b/src/test/java/com/firebolt/jdbc/RawStatementTest.java
index 20e03ade9..197b23ace 100644
--- a/src/test/java/com/firebolt/jdbc/RawStatementTest.java
+++ b/src/test/java/com/firebolt/jdbc/RawStatementTest.java
@@ -6,6 +6,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 
+import com.firebolt.jdbc.metadata.MetadataUtil.Query;
 import org.junit.jupiter.api.Test;
 
 class RawStatementTest {
diff --git a/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java b/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java
index 908d24d5c..eb0595b81 100644
--- a/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
 package com.firebolt.jdbc.client.account;
 
 import com.fasterxml.jackson.databind.DeserializationFeature;
@@ -204,3 +205,5 @@ private Map<String, String> extractHeadersMap(Request request) {
 		return headers;
 	}
 }
+=======
+>>>>>>> 5242315 (Start adding support for new identity)
diff --git a/src/test/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactoryTest.java b/src/test/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactoryTest.java
deleted file mode 100644
index 4a0aaebe2..000000000
--- a/src/test/java/com/firebolt/jdbc/client/authentication/AuthenticationRequestFactoryTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.firebolt.jdbc.client.authentication;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import org.junit.jupiter.api.Test;
-
-class AuthenticationRequestFactoryTest {
-
-	@Test
-	void shouldGetServiceAccountRequestWhenUsernameDoesNotContainSpecialCharacter() {
-		String name = "265576ea-2478-4209-860c-f75f55e7c1f7";
-		String password = "hello";
-		AuthenticationRequest rq = AuthenticationRequestFactory.getAuthenticationRequest(name, password, "localhost");
-		assertTrue(rq instanceof ServiceAccountAuthenticationRequest);
-	}
-
-	@Test
-	void shouldGetUsernamePasswordRqWhenUsernameIsAnEmailAddress() {
-		String name = "tester@firebolt.io";
-		String password = "hello";
-		AuthenticationRequest rq = AuthenticationRequestFactory.getAuthenticationRequest(name, password, "localhost");
-		assertTrue(rq instanceof UsernamePasswordAuthenticationRequest);
-	}
-
-	@Test
-	void shouldGetUsernamePasswordRqWhenUsernameIsNullOrEmpty() {
-		assertTrue(AuthenticationRequestFactory.getAuthenticationRequest(null, null,
-				null) instanceof UsernamePasswordAuthenticationRequest);
-		assertTrue(AuthenticationRequestFactory.getAuthenticationRequest("", null,
-				null) instanceof UsernamePasswordAuthenticationRequest);
-	}
-}
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClientTest.java b/src/test/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClientTest.java
index 3e6c3e5a1..bc8f349f8 100644
--- a/src/test/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClientTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClientTest.java
@@ -30,6 +30,8 @@ class FireboltAuthenticationClientTest {
 	private static final String USER = "usr";
 	private static final String PASSWORD = "PA§§WORD";
 
+	private static final String ENV = "ENV";
+
 	@Spy
 	private final ObjectMapper objectMapper = new ObjectMapper()
 			.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
@@ -62,7 +64,7 @@ void shouldPostConnectionTokens() throws IOException, FireboltException {
 				FireboltAuthenticationResponse.builder().accessToken("a").refreshToken("r").expiresIn(1).build());
 		when(body.string()).thenReturn(tokensResponse);
 
-		fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD);
+		fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD, ENV);
 
 		verify(httpClient).newCall(requestArgumentCaptor.capture());
 		Request actualPost = requestArgumentCaptor.getValue();
@@ -82,7 +84,7 @@ void shouldThrowExceptionWhenStatusCodeIsNotFound() throws Exception {
 		when(httpClient.newCall(any())).thenReturn(call);
 
 		assertThrows(FireboltException.class,
-				() -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD));
+				() -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD, ENV));
 	}
 
 	@Test
@@ -91,7 +93,7 @@ void shouldNotRetryWhenFacingANonRetryableException() throws Exception {
 		when(call.execute()).thenThrow(IOException.class);
 		when(httpClient.newCall(any())).thenReturn(call);
 
-		assertThrows(IOException.class, () -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD));
+		assertThrows(IOException.class, () -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD, ENV));
 		verify(call).execute();
 		verify(call, times(0)).clone();
 	}
@@ -107,6 +109,6 @@ void shouldThrowExceptionWhenStatusCodeIsForbidden() throws Exception {
 		when(httpClient.newCall(any())).thenReturn(call);
 
 		assertThrows(FireboltException.class,
-				() -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD));
+				() -> fireboltAuthenticationClient.postConnectionTokens(HOST, USER, PASSWORD, ENV));
 	}
 }
diff --git a/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java b/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
index 0df3cf7e7..e2c887f5d 100644
--- a/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
@@ -14,18 +14,12 @@ class ServiceAccountAuthenticationRequestTest {
 	@Test
 	void shouldCreateHttpEntityWithTheProvidedCredentials() throws IOException {
 		ServiceAccountAuthenticationRequest serviceAccountAuthenticationHttpRequest = new ServiceAccountAuthenticationRequest(
-				"he-ll-o", "secret", "https://api.dev.firebolt.io:443");
+			"he-ll-o",	"secret", "dev");
 		RequestBody requestBody = serviceAccountAuthenticationHttpRequest.getRequestBody();
 		Buffer buffer = new Buffer();
 		requestBody.writeTo(buffer);
 
-		assertEquals("client_id=he-ll-o&client_secret=secret&grant_type=client_credentials", buffer.readUtf8());
+		assertEquals("audience=https%3A%2F%2Fdev-firebolt-v2.us.auth0.com%2Fapi%2Fv2%2F&grant_type=client_credentials&client_id=he-ll-o&client_secret=secret", buffer.readUtf8());
 	}
 
-	@Test
-	void shouldGetUri() {
-		ServiceAccountAuthenticationRequest serviceAccountAuthenticationHttpRequest = new ServiceAccountAuthenticationRequest(
-				"he-ll-o", "secret", "https://api.dev.firebolt.io:443");
-		assertEquals("https://api.dev.firebolt.io:443/auth/v1/token", serviceAccountAuthenticationHttpRequest.getUri());
-	}
 }
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequestTest.java b/src/test/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequestTest.java
deleted file mode 100644
index f16b0bb54..000000000
--- a/src/test/java/com/firebolt/jdbc/client/authentication/UsernamePasswordAuthenticationRequestTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.firebolt.jdbc.client.authentication;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.jupiter.api.Test;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import okhttp3.RequestBody;
-import okio.Buffer;
-
-class UsernamePasswordAuthenticationRequestTest {
-
-	@Test
-	void shouldCreateHttpEntityWithTheProvidedCredentials() throws IOException {
-		UsernamePasswordAuthenticationRequest usernamePasswordAuthenticationHttpRequest = new UsernamePasswordAuthenticationRequest(
-				"hello", "pa$$word", "https://api.dev.firebolt.io:443");
-		RequestBody requestBody = usernamePasswordAuthenticationHttpRequest.getRequestBody();
-		Buffer buffer = new Buffer();
-		requestBody.writeTo(buffer);
-		// We transform the requests to map because the order of the fields is not
-		// guaranteed
-		Map<String, Object> expectedRequest = new ObjectMapper()
-				.readValue("{\"username\":\"hello\",\"password\":\"pa$$word\"}", HashMap.class);
-		Map<String, Object> actualRequest = new ObjectMapper().readValue(buffer.readUtf8(), HashMap.class);
-		assertEquals(expectedRequest, actualRequest);
-	}
-
-	@Test
-	void getUri() {
-		UsernamePasswordAuthenticationRequest usernamePasswordAuthenticationHttpRequest = new UsernamePasswordAuthenticationRequest(
-				"hello", "pa$$word", "https://api.dev.firebolt.io:443");
-		assertEquals("https://api.dev.firebolt.io:443/auth/v1/login",
-				usernamePasswordAuthenticationHttpRequest.getUri());
-	}
-}
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
new file mode 100644
index 000000000..27b666790
--- /dev/null
+++ b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
@@ -0,0 +1,72 @@
+package com.firebolt.jdbc.client.gateway;
+
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import com.firebolt.jdbc.exception.ExceptionType;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.firebolt.jdbc.connection.FireboltConnection;
+import com.firebolt.jdbc.exception.FireboltException;
+
+import okhttp3.Call;
+import okhttp3.OkHttpClient;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+
+@ExtendWith(MockitoExtension.class)
+class FireboltGatewayUrlClientTest {
+
+	@Spy
+	private final ObjectMapper objectMapper = new ObjectMapper();
+
+	@Mock
+	private OkHttpClient httpClient;
+
+	@Mock
+	private FireboltConnection fireboltConnection;
+
+    @InjectMocks
+    private FireboltGatewayUrlClient fireboltGatewayUrlClient;
+
+	@Test
+	void shouldGetGatewayUrlWhenResponseIsOk() throws IOException, FireboltException {
+        GatewayUrlResponse response = GatewayUrlResponse.builder().engineUrl("http://engine").build();
+        injectMockedResponse(httpClient, HTTP_OK, response);
+        assertEquals("http://engine", fireboltGatewayUrlClient.getGatewayUrl("access_token", "account").getEngineUrl());
+	}
+
+    @Test
+    void shouldThrowFireboltExceptionUponException() {
+        when(httpClient.newCall(any())).thenThrow(new IllegalArgumentException("ex"));
+        Exception ex = assertThrows(FireboltException.class, () ->fireboltGatewayUrlClient.getGatewayUrl("token", "acc"));
+        assertEquals("Failed to get gateway url for account acc", ex.getMessage());
+    }
+
+    private void injectMockedResponse(OkHttpClient httpClient, int code, GatewayUrlResponse gatewayUrlResponse) throws IOException {
+        Response response = mock(Response.class);
+        Call call = mock(Call.class);
+        when(httpClient.newCall(any())).thenReturn(call);
+        when(call.execute()).thenReturn(response);
+        ResponseBody body = mock(ResponseBody.class);
+        when(response.body()).thenReturn(body);
+        when(response.code()).thenReturn(code);
+        String gatewayResponse = new ObjectMapper()
+                .writeValueAsString(gatewayUrlResponse);
+        when(body.string()).thenReturn(gatewayResponse);
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
index d360be097..bf4a7c0ad 100644
--- a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
@@ -8,11 +8,9 @@
 import com.firebolt.jdbc.statement.StatementInfoWrapper;
 import com.firebolt.jdbc.statement.StatementUtil;
 import lombok.NonNull;
-import okhttp3.Call;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
+import okhttp3.*;
 import okio.Buffer;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
@@ -28,7 +26,6 @@
 import java.util.Optional;
 
 import static com.firebolt.jdbc.client.UserAgentFormatter.userAgent;
-import static java.lang.String.format;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
@@ -45,11 +42,14 @@ class StatementClientImplTest {
 	private FireboltConnection connection;
 
 	@Test
+	@Disabled("Disabled until engine_url is available")
 	void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db1").compress(true)
 				.host("firebolt1").port(555).build();
 		when(connection.getAccessToken())
 				.thenReturn(Optional.of("token"));
+
+		injectMockedResponse(okHttpClient, 200);
 		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
 				"ConnA:1.0.9", "ConnB:2.0.9");
 		Call call = getMockedCallWithResponse(200);
@@ -66,8 +66,8 @@ void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 
 		assertEquals(expectedHeaders, extractHeadersMap(actualRequest));
 		assertEquals("show databases;", actualQuery);
-		assertEquals(format(
-				"http://firebolt1:555/?result_overflow_mode=break&database=db1&output_format=TabSeparatedWithNamesAndTypes&query_id=%s&compress=1&max_result_rows=1&max_execution_time=15",
+		assertEquals(String.format(
+				"http://firebolt1:555/dynamic/query?result_overflow_mode=break&database=db1&output_format=TabSeparatedWithNamesAndTypes&query_id=1cfd2cc6-3a62-48e2-ac9c-83846d70f16a&compress=1&max_result_rows=1&max_execution_time=15",
 				statementInfoWrapper.getId()), actualRequest.url().toString());
 	}
 
@@ -79,6 +79,7 @@ void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException,
 				.thenReturn(Optional.of("token"));
 		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
 				"ConnA:1.0.9", "ConnB:2.0.9");
+		injectMockedResponse(okHttpClient, 200);
 		Call call = getMockedCallWithResponse(200);
 		when(okHttpClient.newCall(any())).thenReturn(call);
 		StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("show databases").get(0);
@@ -89,7 +90,7 @@ void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException,
 		String actualQuery = getActualRequestString(actualRequest);
 
 		assertEquals("show databases;", actualQuery);
-		assertEquals("http://firebolt1:555/?output_format=TabSeparatedWithNamesAndTypes",
+		assertEquals("http://firebolt1:555/dynamic/query?output_format=TabSeparatedWithNamesAndTypes",
 				actualRequest.url().toString());
 	}
 
@@ -99,6 +100,7 @@ void shouldCancelSqlQuery() throws FireboltException, IOException {
 				.host("firebolt1").port(555).build();
 		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection,
 				mock(ObjectMapper.class), "", "");
+		injectMockedResponse(okHttpClient, 200);
 		Call call = getMockedCallWithResponse(200);
 		when(okHttpClient.newCall(any())).thenReturn(call);
 		statementClient.abortStatement("12345", fireboltProperties);
@@ -156,6 +158,17 @@ private Map<String, String> extractHeadersMap(Request request) {
 		return headers;
 	}
 
+
+	private void injectMockedResponse(OkHttpClient httpClient, int code) throws IOException {
+		Response response = mock(Response.class);
+		Call call = mock(Call.class);
+		lenient().when(httpClient.newCall(any())).thenReturn(call);
+		lenient().when(call.execute()).thenReturn(response);
+		ResponseBody body = mock(ResponseBody.class);
+		lenient().when(response.body()).thenReturn(body);
+		lenient().when(response.code()).thenReturn(code);
+	}
+
 	@NonNull
 	private String getActualRequestString(Request actualRequest) throws IOException {
 		Buffer buffer = new Buffer();
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index dbfd1dfd7..aa65e43a5 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -13,9 +13,12 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 
+import com.firebolt.jdbc.service.FireboltEngineService;
+import com.firebolt.jdbc.service.FireboltGatewayUrlService;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
@@ -25,15 +28,17 @@
 import com.firebolt.jdbc.exception.ExceptionType;
 import com.firebolt.jdbc.exception.FireboltException;
 import com.firebolt.jdbc.service.FireboltAuthenticationService;
-import com.firebolt.jdbc.service.FireboltEngineService;
 import com.firebolt.jdbc.service.FireboltStatementService;
 import com.firebolt.jdbc.statement.StatementInfoWrapper;
 
 @ExtendWith(MockitoExtension.class)
 class FireboltConnectionTest {
 
-	private static final String URL = "jdbc:firebolt://api.dev.firebolt.io/db";
-	private static final String LOCAL_URL = "jdbc:firebolt://localhost:8123/local_dev_db?ssl=false&max_query_size=10000000&use_standard_sql=1&mask_internal_errors=0&firebolt_enable_beta_functions=1&firebolt_case_insensitive_identifiers=1&rest_api_pull_timeout_sec=3600&rest_api_pull_interval_millisec=5000&rest_api_retry_times=10";
+	private static final String URL = "jdbc:firebolt:db?env=dev&engine=eng";
+
+	private static final String SYSTEM_ENGINE_URL = "jdbc:firebolt:db?env=dev&engine=system";
+
+	private static final String LOCAL_URL = "jdbc:firebolt:local_dev_db?ssl=false&max_query_size=10000000&use_standard_sql=1&mask_internal_errors=0&firebolt_enable_beta_functions=1&firebolt_case_insensitive_identifiers=1&rest_api_pull_timeout_sec=3600&rest_api_pull_interval_millisec=5000&rest_api_retry_times=10&host=localhost";
 	private final FireboltConnectionTokens fireboltConnectionTokens = FireboltConnectionTokens.builder().build();
 	@Captor
 	private ArgumentCaptor<FireboltProperties> propertiesArgumentCaptor;
@@ -41,6 +46,9 @@ class FireboltConnectionTest {
 	private ArgumentCaptor<StatementInfoWrapper> queryInfoWrapperArgumentCaptor;
 	@Mock
 	private FireboltAuthenticationService fireboltAuthenticationService;
+	@Mock
+	private FireboltGatewayUrlService fireboltGatewayUrlService;
+
 	@Mock
 	private FireboltEngineService fireboltEngineService;
 	@Mock
@@ -55,31 +63,31 @@ void init() throws FireboltException {
 		connectionProperties.put("compress", "1");
 		lenient().when(fireboltAuthenticationService.getConnectionTokens(eq("https://api.dev.firebolt.io:443"), any()))
 				.thenReturn(fireboltConnectionTokens);
-		lenient().when(fireboltEngineService.getEngine(any(), any(), any())).thenReturn(mock(Engine.class));
+		lenient().when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("url");
 	}
 
 	@Test
 	void shouldInitConnection() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertFalse(fireboltConnection.isClosed());
 	}
 
 	@Test
 	void shouldNotFetchTokenNorEngineHostForLocalFirebolt() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(LOCAL_URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		verifyNoInteractions(fireboltAuthenticationService);
-		verifyNoInteractions(fireboltEngineService);
+		verifyNoInteractions(fireboltGatewayUrlService);
 		assertFalse(fireboltConnection.isClosed());
 	}
 
 	@Test
 	void shouldPrepareStatement() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
 				.thenReturn(Optional.empty());
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		PreparedStatement statement = fireboltConnection
 				.prepareStatement("INSERT INTO cars(sales, name) VALUES (?, ?)");
 		statement.setObject(1, 500);
@@ -87,8 +95,7 @@ void shouldPrepareStatement() throws SQLException {
 		statement.execute();
 		assertNotNull(fireboltConnection);
 		assertNotNull(statement);
-		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), any(), anyInt(), anyInt(),
-				anyBoolean(), any());
+		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any());
 		assertEquals("INSERT INTO cars(sales, name) VALUES (500, 'Ford')",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
@@ -96,7 +103,7 @@ void shouldPrepareStatement() throws SQLException {
 	@Test
 	void shouldCloseAllStatementsOnClose() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		Statement statement = fireboltConnection.createStatement();
 		Statement preparedStatement = fireboltConnection.prepareStatement("test");
 		fireboltConnection.close();
@@ -108,15 +115,15 @@ void shouldCloseAllStatementsOnClose() throws SQLException {
 	@Test
 	void shouldNotSetNewPropertyWhenConnectionIsNotValidWithTheNewProperty() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
 				.thenThrow(new FireboltException(ExceptionType.TOO_MANY_REQUESTS));
 		assertThrows(FireboltException.class,
 				() -> fireboltConnection.addProperty(new ImmutablePair<>("custom_1", "1")));
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), any());
+				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
 		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
 		assertNull(fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
@@ -124,17 +131,17 @@ void shouldNotSetNewPropertyWhenConnectionIsNotValidWithTheNewProperty() throws
 
 	@Test
 	void shouldSetNewPropertyWhenConnectionIsValidWithTheNewProperty() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
 				.thenReturn(Optional.empty());
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 
 		Pair<String, String> newProperties = new ImmutablePair<>("custom_1", "1");
 
 		fireboltConnection.addProperty(newProperties);
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), any());
+				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
 		assertEquals("1", fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
 		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
@@ -142,23 +149,22 @@ void shouldSetNewPropertyWhenConnectionIsValidWithTheNewProperty() throws SQLExc
 
 	@Test
 	void shouldValidateConnectionWhenCallingIsValid() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.empty());
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		fireboltConnection.isValid(500);
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), any());
+				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
 
 	@Test
 	void shouldNotValidateConnectionWhenCallingIsValidWhenUsingSystemEngine() throws SQLException {
 		Properties propertiesWithSystemEngine = new Properties(connectionProperties);
-		propertiesWithSystemEngine.put("engine_name", "system");
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, propertiesWithSystemEngine,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+		FireboltConnection fireboltConnection = new FireboltConnection(SYSTEM_ENGINE_URL, propertiesWithSystemEngine,
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		fireboltConnection.isValid(500);
 
 		verifyNoInteractions(fireboltStatementService);
@@ -166,52 +172,52 @@ void shouldNotValidateConnectionWhenCallingIsValidWhenUsingSystemEngine() throws
 
 	@Test
 	void shouldIgnore429WhenValidatingConnection() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenThrow(new FireboltException(ExceptionType.TOO_MANY_REQUESTS));
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertTrue(fireboltConnection.isValid(500));
 	}
 
 	@Test
 	void shouldReturnFalseWhenValidatingConnectionThrowsAnException() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenThrow(new FireboltException(ExceptionType.ERROR));
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertFalse(fireboltConnection.isValid(500));
 	}
 
 	@Test
 	void shouldThrowExceptionWhenValidatingConnectionWithNegativeTimeout() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertThrows(FireboltException.class, () -> fireboltConnection.isValid(-1));
 	}
 
 	@Test
 	void shouldReturnFalseWhenValidatingClosedConnection() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		fireboltConnection.close();
 		assertFalse(fireboltConnection.isValid(50));
 	}
 
 	@Test
 	void shouldExtractConnectorOverrides() throws SQLException {
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.empty());
 		connectionProperties.put("user_clients", "ConnA:1.0.9,ConnB:2.8.0");
 		connectionProperties.put("user_drivers", "DriverA:2.0.9,DriverB:3.8.0");
 
 		FireboltConnection fireboltConnectionImpl = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 
 		PreparedStatement statement = fireboltConnectionImpl.prepareStatement("SELECT 1");
 		statement.execute();
 
 		verify(fireboltStatementService).execute(any(), propertiesArgumentCaptor.capture(), anyInt(), anyInt(),
-				anyBoolean(), any());
+				anyBoolean(), anyBoolean(), any());
 		assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_clients"));
 		assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_drivers"));
 		assertNull(fireboltConnectionImpl.getSessionProperties().getAdditionalProperties().get("user_clients"));
@@ -219,18 +225,19 @@ void shouldExtractConnectorOverrides() throws SQLException {
 	}
 
 	@Test
+	@Disabled("System engine is used until engine_url is available")
 	void shouldGetEngineNameFromHost() throws SQLException {
-		when(fireboltEngineService.getEngineNameFromHost(any())).thenReturn("myHost_345");
+		connectionProperties.put("engine", "hello");
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
-		assertEquals("myHost_345", fireboltConnection.getEngine());
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
+		assertEquals("hello", fireboltConnection.getEngine());
 	}
 
 	@Test
 	void shouldInitNetworkTimeoutWithPropertyByDefault() throws SQLException {
 		connectionProperties.put("socket_timeout_millis", "60");
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertEquals(60, fireboltConnection.getNetworkTimeout());
 	}
 
@@ -238,14 +245,14 @@ void shouldInitNetworkTimeoutWithPropertyByDefault() throws SQLException {
 	void shouldInitConnectionTimeoutWithPropertyByDefault() throws SQLException {
 		connectionProperties.put("connection_timeout_millis", "50");
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertEquals(50, fireboltConnection.getConnectionTimeout());
 	}
 
 	@Test
 	void shouldCloseConnectionWhenAbortingConnection() throws SQLException, InterruptedException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		ExecutorService executorService = Executors.newFixedThreadPool(10);
 		fireboltConnection.abort(executorService);
 		executorService.awaitTermination(1, TimeUnit.SECONDS);
@@ -260,8 +267,10 @@ void shouldRemoveExpiredToken() throws SQLException {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			when(fireboltAuthenticationService.getConnectionTokens("http://host:8080", fireboltProperties))
 					.thenReturn(FireboltConnectionTokens.builder().build());
+			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://hello").build());
+
 			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 			fireboltConnection.removeExpiredTokens();
 			verify(fireboltAuthenticationService).removeConnectionTokens("http://host:8080", fireboltProperties);
 		}
@@ -277,8 +286,9 @@ void shouldReturnConnectionTokenWhenAvailable() throws SQLException {
 			FireboltConnectionTokens connectionTokens = FireboltConnectionTokens.builder().accessToken(accessToken).build();
 			when(fireboltAuthenticationService.getConnectionTokens(eq("http://host:8080"), any()))
 					.thenReturn(connectionTokens);
+			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://engineHost").build());
 			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 			verify(fireboltAuthenticationService).getConnectionTokens("http://host:8080", fireboltProperties);
 			assertEquals(accessToken, fireboltConnection.getAccessToken().get());
 		}
@@ -291,7 +301,7 @@ void shouldNotReturnConnectionTokenWithLocalDb() throws SQLException {
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 			assertEquals(Optional.empty(), fireboltConnection.getAccessToken());
 			verifyNoInteractions(fireboltAuthenticationService);
 		}
@@ -304,7 +314,7 @@ void shouldSetNetworkTimeout() throws SQLException {
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 			assertEquals(5, fireboltConnection.getNetworkTimeout());
 			fireboltConnection.setNetworkTimeout(null, 1);
 			assertEquals(1, fireboltConnection.getNetworkTimeout());
@@ -318,7 +328,7 @@ void shouldUseConnectionTimeoutFromProperties() throws SQLException {
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 			assertEquals(20, fireboltConnection.getConnectionTimeout());
 		}
 	}
@@ -326,7 +336,7 @@ void shouldUseConnectionTimeoutFromProperties() throws SQLException {
 	@Test
 	void shouldThrowExceptionWhenTryingToUseClosedConnection() throws SQLException {
 		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltEngineService, fireboltStatementService);
+				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		fireboltConnection.close();
 		assertThrows(FireboltException.class, fireboltConnection::getCatalog);
 	}
@@ -334,7 +344,7 @@ void shouldThrowExceptionWhenTryingToUseClosedConnection() throws SQLException {
 	@Test
 	void shouldUnwrapFireboltConnection() throws SQLException {
 		Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltEngineService, fireboltStatementService);
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 		assertTrue(connection.isWrapperFor(FireboltConnection.class));
 		assertEquals(connection, connection.unwrap(FireboltConnection.class));
 	}
@@ -342,17 +352,18 @@ void shouldUnwrapFireboltConnection() throws SQLException {
 	@Test
 	void shouldThrowExceptionWhenCannotUnwrap() throws SQLException {
 		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltEngineService, fireboltStatementService)) {
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
 			assertFalse(connection.isWrapperFor(String.class));
 			assertThrows(SQLException.class, () -> connection.unwrap(String.class));
 		}
 	}
 
 	@Test
+	@Disabled("Db is currently not supported")
 	void shouldGetDatabaseWhenGettingCatalog() throws SQLException {
 		connectionProperties.put("database", "db");
 		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltEngineService, fireboltStatementService)) {
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
 			assertEquals("db", connection.getCatalog());
 		}
 	}
@@ -361,7 +372,7 @@ void shouldGetDatabaseWhenGettingCatalog() throws SQLException {
 	void shouldGetNoneTransactionIsolation() throws SQLException {
 		connectionProperties.put("database", "db");
 		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltEngineService, fireboltStatementService)) {
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
 			assertEquals(Connection.TRANSACTION_NONE, connection.getTransactionIsolation());
 		}
 	}
@@ -370,9 +381,47 @@ void shouldGetNoneTransactionIsolation() throws SQLException {
 	void shouldThrowExceptionWhenPreparingStatementWIthInvalidResultSetType() throws SQLException {
 		connectionProperties.put("database", "db");
 		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltEngineService, fireboltStatementService)) {
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
 			assertThrows(SQLFeatureNotSupportedException.class,
 					() -> connection.prepareStatement("any", TYPE_SCROLL_INSENSITIVE, 0));
 		}
 	}
+
+	@Test
+	@Disabled("Disabled until engine_url is available")
+	void shouldGetDefaultEngineWhenEngineIsNotProvided() throws SQLException {
+		connectionProperties.put("engine", "");
+		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().name("default_engine").endpoint("http://my-endpoint").build());
+		try (FireboltConnection  connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+			verify(fireboltEngineService).getEngine(null, "db");
+			assertEquals("default_engine", connection.getSessionProperties().getEngine());
+			assertEquals("my-endpoint", connection.getSessionProperties().getHost());
+		}
+	}
+
+	@Test
+	@Disabled("Disabled until engine_url is available")
+	void shouldGetEngineUrlWhenEngineIsProvided() throws SQLException {
+		connectionProperties.put("engine", "engine");
+		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("http://my_endpoint").build());
+		try (FireboltConnection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+			verify(fireboltEngineService).getEngine("engine", null);
+			assertEquals("http://my_endpoint", connection.getSessionProperties().getHost());
+		}
+	}
+
+	@Test
+	@Disabled("Db is currently not supported")
+	void shouldNotGetEngineUrlOrDefaultEngineUrlWhenUsingSystemEngine() throws SQLException {
+		connectionProperties.put("engine", "system");
+		when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://my_endpoint");
+
+		try (FireboltConnection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
+				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+			verify(fireboltEngineService, times(0)).getEngine(any(), any());
+			assertEquals("http://my_endpoint", connection.getSessionProperties().getHost());
+		}
+	}
 }
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtilTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtilTest.java
deleted file mode 100644
index 598a6429c..000000000
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltJdbcUrlUtilTest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.firebolt.jdbc.connection;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.util.Properties;
-
-import org.junit.jupiter.api.Test;
-
-class FireboltJdbcUrlUtilTest {
-
-	@Test
-	void shouldGetAllPropertiesFromUri() {
-		String uri = "jdbc:firebolt://api.dev.firebolt.io:123/Tutorial_11_05?use_standard_sql=0&account=firebolt";
-		Properties properties = FireboltJdbcUrlUtil.extractProperties(uri);
-
-		Properties expectedProperties = new Properties();
-		expectedProperties.put("path", "/Tutorial_11_05");
-		expectedProperties.put("host", "api.dev.firebolt.io");
-		expectedProperties.put("port", "123");
-		expectedProperties.put("use_standard_sql", "0");
-		expectedProperties.put("account", "firebolt");
-
-		assertEquals(expectedProperties, properties);
-	}
-}
diff --git a/src/test/java/com/firebolt/jdbc/connection/UrlUtilTest.java b/src/test/java/com/firebolt/jdbc/connection/UrlUtilTest.java
new file mode 100644
index 000000000..d0e0ceacf
--- /dev/null
+++ b/src/test/java/com/firebolt/jdbc/connection/UrlUtilTest.java
@@ -0,0 +1,29 @@
+package com.firebolt.jdbc.connection;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.Properties;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+class UrlUtilTest {
+
+
+	@ParameterizedTest
+	@CsvSource({
+			"jdbc:firebolt:Tutorial_11_05/?use_standard_sql=0&host=api.dev.firebolt.io&account=firebolt, Tutorial_11_05, api.dev.firebolt.io, 0, firebolt",
+			"jdbc:firebolt:Tutorial_11_05?use_standard_sql=0&host=api.dev.firebolt.io&account=firebolt, Tutorial_11_05, api.dev.firebolt.io, 0, firebolt",
+			"jdbc:firebolt:/?use_standard_sql=0&host=api.dev.firebolt.io&account=firebolt, '', api.dev.firebolt.io, 0, firebolt"
+	})
+	void shouldGetAllPropertiesFromUri(String uri, String expectedPath, String expectedHost, String expectedUseStandardSql, String expectedAccount) {
+		Properties properties = UrlUtil.extractProperties(uri);
+		Properties expectedProperties = new Properties();
+		expectedProperties.put("path", expectedPath);
+		expectedProperties.put("host", expectedHost);
+		expectedProperties.put("use_standard_sql", expectedUseStandardSql);
+		expectedProperties.put("account", expectedAccount);
+		assertEquals(expectedProperties, properties);
+	}
+
+}
diff --git a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
index 8edc77e92..a583c8939 100644
--- a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
@@ -13,12 +13,12 @@ class FireboltPropertiesTest {
 	@Test
 	void shouldHaveDefaultPropertiesWhenOnlyTheRequiredFieldsAreSpecified() {
 		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().database("db").bufferSize(65536)
-				.sslCertificatePath("").sslMode("strict").path("/").port(443) // 443 by default as SSL is enabled by
-																				// default
-				.compress(true).user(null).password(null).host("host").ssl(true).additionalProperties(new HashMap<>())
-				.account(null).engine(null).keepAliveTimeoutMillis(300000).maxConnectionsTotal(300).maxRetries(3)
-				.socketTimeoutMillis(0).connectionTimeoutMillis(60000).tcpKeepInterval(30).tcpKeepIdle(60)
-				.tcpKeepCount(10).build();
+				.sslCertificatePath("").sslMode("strict").path("").port(443) // 443 by default as SSL is enabled by
+				.systemEngine(false).compress(true)													// default
+				.user(null).password(null).host("host").ssl(true).additionalProperties(new HashMap<>())
+				.account(null).keepAliveTimeoutMillis(300000).maxConnectionsTotal(300).maxRetries(3)
+				.socketTimeoutMillis(0).connectionTimeoutMillis(60000).tcpKeepInterval(30).environment("app").tcpKeepIdle(60)
+				.tcpKeepCount(10).account("firebolt").build();
 
 		Properties properties = new Properties();
 		properties.put("host", "host");
@@ -36,7 +36,7 @@ void shouldHaveAllTheSpecifiedCustomProperties() {
 		properties.put("database", "myDb");
 		properties.put("ssl_certificate_path", "root_cert");
 		properties.put("ssl_mode", "none");
-		properties.put("path", "/example");
+		properties.put("path", "example");
 		properties.put("someCustomProperties", "custom_value");
 		properties.put("compress", "1");
 
@@ -44,18 +44,18 @@ void shouldHaveAllTheSpecifiedCustomProperties() {
 		customProperties.put("someCustomProperties", "custom_value");
 
 		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().bufferSize(51)
-				.sslCertificatePath("root_cert").sslMode("none").path("/example").database("myDb").compress(true)
-				.port(443).user(null).password(null).host("myDummyHost").ssl(true)
-				.additionalProperties(customProperties).account(null).engine(null).keepAliveTimeoutMillis(300000)
+				.sslCertificatePath("root_cert").sslMode("none").path("example").database("myDb").compress(true)
+				.port(443).user(null).password(null).host("myDummyHost").ssl(true).systemEngine(false)
+				.additionalProperties(customProperties).account(null).keepAliveTimeoutMillis(300000)
 				.maxConnectionsTotal(300).maxRetries(3).socketTimeoutMillis(20).connectionTimeoutMillis(60000)
-				.tcpKeepInterval(30).tcpKeepIdle(60).tcpKeepCount(10).build();
+				.tcpKeepInterval(30).tcpKeepIdle(60).tcpKeepCount(10).environment("app").account("firebolt").build();
 		assertEquals(expectedDefaultProperties, FireboltProperties.of(properties));
 	}
 
 	@Test
 	void shouldUsePathParamAsDb() {
 		Properties properties = new Properties();
-		properties.put("path", "/example");
+		properties.put("path", "example");
 		properties.put("host", "host");
 
 		assertEquals("example", FireboltProperties.of(properties).getDatabase());
@@ -64,7 +64,7 @@ void shouldUsePathParamAsDb() {
 	@Test
 	void shouldSupportBooleansForBooleanProperties() {
 		Properties properties = new Properties();
-		properties.put("path", "/example");
+		properties.put("path", "example");
 		properties.put("host", "host");
 		properties.put("ssl", "true");
 		properties.put("compress", "false");
@@ -76,7 +76,7 @@ void shouldSupportBooleansForBooleanProperties() {
 	@Test
 	void shouldSupportIntForBooleanProperties() {
 		Properties properties = new Properties();
-		properties.put("path", "/example");
+		properties.put("path", "example");
 		properties.put("host", "host");
 		properties.put("ssl", "2");
 		properties.put("compress", "0");
@@ -88,7 +88,7 @@ void shouldSupportIntForBooleanProperties() {
 	@Test
 	void shouldUseCustomPortWhenProvided() {
 		Properties properties = new Properties();
-		properties.put("path", "/example");
+		properties.put("path", "example");
 		properties.put("host", "host");
 		properties.put("port", "999");
 
@@ -96,35 +96,46 @@ void shouldUseCustomPortWhenProvided() {
 	}
 
 	@Test
-	void shouldThrowExceptionWhenNoDbProvided() {
+	void shouldUseSystemEngineWhenNoDbOrEngineProvided() {
 		Properties properties = new Properties();
-		properties.put("host", "host");
-
-		assertThrows(IllegalArgumentException.class, () -> FireboltProperties.of(properties));
+		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
+		assertTrue(FireboltProperties.of(properties).isSystemEngine());
+		assertEquals("system", fireboltProperties.getEngine());
+		assertNull(fireboltProperties.getDatabase());
+		assertFalse(fireboltProperties.isCompress());
 	}
 
 	@Test
-	void shouldThrowExceptionWhenHostIsNotProvided() {
+	void shouldNotUseSystemEngineWhenDbAsPathIsProvided() {
 		Properties properties = new Properties();
-		assertThrows(IllegalArgumentException.class, () -> FireboltProperties.of(properties));
+		properties.put("path", "example");
+		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
+		assertFalse(FireboltProperties.of(properties).isSystemEngine());
+		assertNull(fireboltProperties.getEngine());
+		assertEquals("example", fireboltProperties.getDatabase());
+		assertTrue(fireboltProperties.isCompress());
 	}
 
 	@Test
-	void shouldThrowExceptionWhenDbPathFormatIsInvalid() {
+	void shouldNotUseSystemEngineWhenDbAsQueryParamIsProvided() {
 		Properties properties = new Properties();
-		properties.put("path", "");
-		properties.put("host", "host");
-
-		assertThrows(IllegalArgumentException.class, () -> FireboltProperties.of(properties));
+		properties.put("database", "example");
+		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
+		assertFalse(FireboltProperties.of(properties).isSystemEngine());
+		assertNull(fireboltProperties.getEngine());
+		assertEquals("example", fireboltProperties.getDatabase());
+		assertTrue(fireboltProperties.isCompress());
 	}
 
 	@Test
-	void shouldNotReturnAliasAsCustomProperty() {
+	void shouldNotUseSystemEngineWhenEngineIsProvided() {
 		Properties properties = new Properties();
-		properties.put("path", "");
-		properties.put("host", "host");
-
-		assertThrows(IllegalArgumentException.class, () -> FireboltProperties.of(properties));
+		properties.put("engine", "example");
+		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
+		assertFalse(FireboltProperties.of(properties).isSystemEngine());
+		assertNull(fireboltProperties.getDatabase());
+		assertEquals("example", fireboltProperties.getEngine());
+		assertTrue(fireboltProperties.isCompress());
 	}
 
 	@Test
@@ -140,4 +151,5 @@ void shouldSupportUserClientsAndDrivers() {
 		assertEquals(clients, FireboltProperties.of(properties).getUserClients());
 		assertEquals(drivers, FireboltProperties.of(properties).getUserDrivers());
 	}
+
 }
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
index e93bee9cb..2a8700549 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
@@ -26,7 +26,9 @@ class FireboltAuthenticationServiceTest {
 	private static final String USER = "usr";
 	private static final String PASSWORD = "PA§§WORD";
 
-	private static final FireboltProperties PROPERTIES = FireboltProperties.builder().user(USER).password(PASSWORD)
+	private static final String ENV = "ENV";
+
+	private static final FireboltProperties PROPERTIES = FireboltProperties.builder().user(USER).password(PASSWORD).environment(ENV)
 			.compress(true).build();
 
 	@Mock
@@ -44,10 +46,10 @@ void shouldGetConnectionToken() throws IOException, FireboltException {
 		String randomHost = UUID.randomUUID().toString();
 		FireboltConnectionTokens tokens = FireboltConnectionTokens.builder().expiresInSeconds(52)
 				.refreshToken("refresh").accessToken("access").build();
-		when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD)).thenReturn(tokens);
+		when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD, ENV)).thenReturn(tokens);
 
 		assertEquals(tokens, fireboltAuthenticationService.getConnectionTokens(randomHost, PROPERTIES));
-		verify(fireboltAuthenticationClient).postConnectionTokens(randomHost, USER, PASSWORD);
+		verify(fireboltAuthenticationClient).postConnectionTokens(randomHost, USER, PASSWORD, ENV);
 	}
 
 	@Test
@@ -55,17 +57,17 @@ void shouldCallClientOnlyOnceWhenServiceCalledTwiceForTheSameHost() throws IOExc
 		String randomHost = UUID.randomUUID().toString();
 		FireboltConnectionTokens tokens = FireboltConnectionTokens.builder().expiresInSeconds(52)
 				.refreshToken("refresh").accessToken("access").build();
-		when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD)).thenReturn(tokens);
+		when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD, ENV)).thenReturn(tokens);
 
 		fireboltAuthenticationService.getConnectionTokens(randomHost, PROPERTIES);
 		assertEquals(tokens, fireboltAuthenticationService.getConnectionTokens(randomHost, PROPERTIES));
-		verify(fireboltAuthenticationClient).postConnectionTokens(randomHost, USER, PASSWORD);
+		verify(fireboltAuthenticationClient).postConnectionTokens(randomHost, USER, PASSWORD, ENV);
 	}
 
 	@Test
 	void shouldThrowExceptionWithServerResponseWhenAResponseIsAvailable() throws IOException, FireboltException {
 		String randomHost = UUID.randomUUID().toString();
-		Mockito.when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD))
+		Mockito.when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD, ENV))
 				.thenThrow(new FireboltException("An error happened during authentication", 403, "INVALID PASSWORD"));
 
 		FireboltException ex = assertThrows(FireboltException.class,
@@ -78,7 +80,7 @@ void shouldThrowExceptionWithServerResponseWhenAResponseIsAvailable() throws IOE
 	@Test
 	void shouldThrowExceptionWithExceptionMessageWhenAResponseIsNotAvailable() throws IOException, FireboltException {
 		String randomHost = UUID.randomUUID().toString();
-		Mockito.when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD))
+		Mockito.when(fireboltAuthenticationClient.postConnectionTokens(randomHost, USER, PASSWORD, ENV))
 				.thenThrow(new NullPointerException("NULL!"));
 
 		FireboltException ex = assertThrows(FireboltException.class,
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
index ec83e03d8..37dd345ba 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
@@ -2,197 +2,95 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
-import com.firebolt.jdbc.client.account.FireboltAccountClient;
-import com.firebolt.jdbc.client.account.response.FireboltAccountResponse;
-import com.firebolt.jdbc.client.account.response.FireboltDefaultDatabaseEngineResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineIdResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineResponse;
-import com.firebolt.jdbc.connection.settings.FireboltProperties;
+import com.firebolt.jdbc.connection.Engine;
+import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
 
 @ExtendWith(MockitoExtension.class)
 class FireboltEngineServiceTest {
 
-	private static final String HOST = "https://host";
-	private static final String ACCOUNT_ID = "account_id";
-	private static final String DB_NAME = "dbName";
-	private static final String ENGINE_NAME = "engineName";
-	private static final String ENGINE_ID = "engineId";
-	private static final String ACCESS_TOKEN = "token";
-
-	@Mock
-	private FireboltAccountClient fireboltAccountClient;
-
 	@InjectMocks
 	private FireboltEngineService fireboltEngineService;
 
-	@Test
-	void shouldGetDefaultDbEngineWhenEngineNameIsNullOrEmpty() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.compress(false).build();
-
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getDefaultEngineByDatabaseName(HOST, ACCOUNT_ID, DB_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltDefaultDatabaseEngineResponse.builder().engineUrl("URL").build());
-		fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN);
-
-		verify(fireboltAccountClient).getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN);
-		verify(fireboltAccountClient).getDefaultEngineByDatabaseName(HOST, ACCOUNT_ID, DB_NAME, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
-	}
-
-	@Test
-	void shouldGThrowExceptionWhenGettingDefaultEngineAndTheUrlReturnedFromTheServerIsNull() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.compress(false).build();
-
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getDefaultEngineByDatabaseName(HOST, ACCOUNT_ID, DB_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltDefaultDatabaseEngineResponse.builder().engineUrl(null).build());
-		FireboltException exception = assertThrows(FireboltException.class,
-				() -> fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN));
-		assertEquals(
-				"There is no Firebolt engine running on https://host attached to the database dbName. To connect first make sure there is a running engine and then try again.",
-				exception.getMessage());
-
-		verify(fireboltAccountClient).getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN);
-		verify(fireboltAccountClient).getDefaultEngineByDatabaseName(HOST, ACCOUNT_ID, DB_NAME, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
-	}
+	@Mock
+	private FireboltConnection fireboltConnection;
 
 	@Test
-	void shouldGetEngineWhenEngineNameIsPresent() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.engine(ENGINE_NAME).compress(false).build();
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineIdResponse.builder()
-						.engine(FireboltEngineIdResponse.Engine.builder().engineId(ENGINE_ID).build()).build());
-		when(fireboltAccountClient.getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineResponse.builder()
-						.engine(FireboltEngineResponse.Engine.builder().endpoint("ANY").build()).build());
-		fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN);
-
-		verify(fireboltAccountClient).getAccount(properties.getHost(), ACCOUNT_ID, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
+	void shouldGetEngineNameFromEngineHost() throws SQLException {
+		assertEquals("myHost_345", fireboltEngineService.getEngineNameByHost("myHost-345.firebolt.io"));
 	}
 
 	@Test
-	void shouldNotGetAccountWhileGettingEngineIfAccountIdIsNotPresent() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).database(DB_NAME)
-				.engine(ENGINE_NAME).compress(false).build();
-		when(fireboltAccountClient.getEngineId(HOST, null, ENGINE_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineIdResponse.builder()
-						.engine(FireboltEngineIdResponse.Engine.builder().engineId(ENGINE_ID).build()).build());
-		when(fireboltAccountClient.getEngine(HOST, null, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineResponse.builder()
-						.engine(FireboltEngineResponse.Engine.builder().endpoint("ANY").build()).build());
-		fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN);
-
-		verify(fireboltAccountClient, times(0)).getAccount(any(), any(), any());
-		verify(fireboltAccountClient).getEngineId(HOST, null, ENGINE_NAME, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngine(HOST, null, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
+	void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromTheHost() {
+		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngineNameByHost("myHost-345"));
 	}
 
 	@Test
-	void shouldThrowExceptionWhenEngineNameIsSpecifiedButUrlIsNotPresentInTheResponse() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.engine(ENGINE_NAME).compress(false).build();
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineIdResponse.builder()
-						.engine(FireboltEngineIdResponse.Engine.builder().engineId(ENGINE_ID).build()).build());
-		when(fireboltAccountClient.getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineResponse.builder()
-						.engine(FireboltEngineResponse.Engine.builder().endpoint(null).build()).build());
-		FireboltException exception = assertThrows(FireboltException.class,
-				() -> fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN));
-		assertEquals(
-				"There is no Firebolt engine running on https://host with the name engineName. To connect first make sure there is a running engine and then try again.",
-				exception.getMessage());
-
-		verify(fireboltAccountClient).getAccount(properties.getHost(), ACCOUNT_ID, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
+	void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromNullHost() {
+		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngineNameByHost(null));
 	}
 
 	@Test
-	void shouldThrowExceptionWhenEngineNameIsSpecifiedButEngineIdIsNotPresentInTheServerResponse() throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.engine(ENGINE_NAME).compress(false).build();
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineIdResponse.builder()
-						.engine(FireboltEngineIdResponse.Engine.builder().engineId(null).build()).build());
-		FireboltException exception = assertThrows(FireboltException.class,
-				() -> fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN));
-		assertEquals(
-				"Failed to extract engine id field from the server response: the response from the server is invalid.",
-				exception.getMessage());
-		verify(fireboltAccountClient).getAccount(properties.getHost(), ACCOUNT_ID, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
+	void shouldGetDefaultEngineWhenEngineNameIsNotProvided() throws SQLException {
+		Statement statement = mock(Statement.class);
+		ResultSet resultSet = mock(ResultSet.class);
+		when(resultSet.next()).thenReturn(true);
+		when(resultSet.getString("status")).thenReturn("running");
+		when(resultSet.getString("engine_url")).thenReturn("https://url");
+		when(resultSet.getString("engine_name")).thenReturn("hello-engine");
+		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
+		when(statement.executeQuery(any())).thenReturn(resultSet);
+		assertEquals(Engine.builder().endpoint("https://url").name("hello-engine").build(),
+				fireboltEngineService.getEngine(null, "db"));
 	}
 
 	@Test
-	void shouldGetEngineNameFromEngineHost() throws SQLException {
-		assertEquals("myHost_345", fireboltEngineService.getEngineNameFromHost("myHost-345.firebolt.io"));
+	void shouldThrowExceptionWhenDefaultEngineNotRunning() throws SQLException {
+		Statement statement = mock(Statement.class);
+		ResultSet resultSet = mock(ResultSet.class);
+		when(resultSet.next()).thenReturn(true);
+		when(resultSet.getString("status")).thenReturn("down");
+		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
+		when(statement.executeQuery(any())).thenReturn(resultSet);
+		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(null, "db"));
 	}
 
 	@Test
-	void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromTheHost() {
-		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngineNameFromHost("myHost-345"));
+	void shouldGetEngineWhenEngineNameIsProvided() throws SQLException {
+		Statement statement = mock(Statement.class);
+		ResultSet resultSet = mock(ResultSet.class);
+		when(resultSet.next()).thenReturn(true);
+		when(resultSet.getString("status")).thenReturn("running");
+		when(resultSet.getString("engine_url")).thenReturn("https://url");
+		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
+		when(statement.executeQuery(any())).thenReturn(resultSet);
+		assertEquals(Engine.builder().endpoint("https://url").name("some-engine").build(),
+				fireboltEngineService.getEngine("some-engine", "db"));
 	}
 
 	@Test
-	void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromNullHost() {
-		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngineNameFromHost(null));
+	void shouldThrowExceptionWhenEngineNotRunning() throws SQLException {
+		Statement statement = mock(Statement.class);
+		ResultSet resultSet = mock(ResultSet.class);
+		when(resultSet.next()).thenReturn(true);
+		when(resultSet.getString("status")).thenReturn("down");
+		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
+		when(statement.executeQuery(any())).thenReturn(resultSet);
+		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine("some-engine", "db"));
 	}
 
-	@ParameterizedTest
-	@ValueSource(strings = { "ENGINE_STATUS_PROVISIONING_STARTED", "ENGINE_STATUS_PROVISIONING_FINISHED",
-			"ENGINE_STATUS_PROVISIONING_PENDING" })
-	void shouldThrowExceptionWhenEngineStatusIndicatesEngineIsStarting(String status) throws Exception {
-		FireboltProperties properties = FireboltProperties.builder().host(HOST).account(ACCOUNT_ID).database(DB_NAME)
-				.engine(ENGINE_NAME).compress(false).build();
-		when(fireboltAccountClient.getAccount(properties.getHost(), properties.getAccount(), ACCESS_TOKEN))
-				.thenReturn(FireboltAccountResponse.builder().accountId(ACCOUNT_ID).build());
-		when(fireboltAccountClient.getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineIdResponse.builder()
-						.engine(FireboltEngineIdResponse.Engine.builder().engineId(ENGINE_ID).build()).build());
-		when(fireboltAccountClient.getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN))
-				.thenReturn(FireboltEngineResponse.builder()
-						.engine(FireboltEngineResponse.Engine.builder().endpoint("ANY").currentStatus(status).build())
-						.build());
-		FireboltException exception = assertThrows(FireboltException.class,
-				() -> fireboltEngineService.getEngine(HOST, properties, ACCESS_TOKEN));
-		assertEquals("The engine engineName is currently starting. Please wait until the engine is on and then execute the query again.",
-				exception.getMessage());
-
-		verify(fireboltAccountClient).getAccount(properties.getHost(), ACCOUNT_ID, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngineId(HOST, ACCOUNT_ID, ENGINE_NAME, ACCESS_TOKEN);
-		verify(fireboltAccountClient).getEngine(HOST, ACCOUNT_ID, ENGINE_NAME, ENGINE_ID, ACCESS_TOKEN);
-		verifyNoMoreInteractions(fireboltAccountClient);
-	}
 }
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltStatementServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltStatementServiceTest.java
index 9500ec4ce..643436829 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltStatementServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltStatementServiceTest.java
@@ -35,9 +35,9 @@ void shouldExecuteQueryAndCreateResultSet() throws SQLException {
 			StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("SELECT 1").get(0);
 			FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("firebolt1")
 					.ssl(true).compress(false).build();
-			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, false);
+			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
 
-			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, 10, -1, true,
+			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, 10, -1, true, false,
 					mock(FireboltStatement.class));
 			verify(statementClient).executeSqlStatement(statementInfoWrapper, fireboltProperties, false, 10, -1, true);
 			Assertions.assertEquals(1, mocked.constructed().size());
@@ -50,8 +50,8 @@ void shouldExecuteQueryWithLocalHostFormatParameters() throws SQLException {
 			StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("SELECT 1").get(0);
 			FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("localhost")
 					.ssl(true).compress(false).build();
-			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, false);
-			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, -1, 10, true,
+			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
+			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, -1, 10, true, false,
 					mock(FireboltStatement.class));
 			Assertions.assertEquals(1, mocked.constructed().size());
 			verify(statementClient).executeSqlStatement(statementInfoWrapper, fireboltProperties, false, -1, 10, true);
@@ -63,7 +63,7 @@ void shouldCancelQueryWithAllRequiredParams() throws FireboltException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("http://firebolt1")
 				.ssl(true).compress(false).build();
 
-		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, false);
+		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
 		fireboltStatementService.abortStatement("123", fireboltProperties);
 		verify(statementClient).abortStatement("123", fireboltProperties);
 	}
@@ -71,9 +71,9 @@ void shouldCancelQueryWithAllRequiredParams() throws FireboltException {
 	@Test
 	void shouldThrowExceptionWhenTryingToCancelQueryWithASystemEngine() throws FireboltException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("http://firebolt1")
-				.ssl(true).compress(false).build();
+				.ssl(true).compress(false).systemEngine(true).build();
 
-		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, true);
+		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
 		assertThrows(FireboltException.class, () -> fireboltStatementService.abortStatement("123", fireboltProperties));
 		verifyNoInteractions(statementClient);
 	}
@@ -84,8 +84,8 @@ void shouldExecuteQueryWithParametersForSystemEngine() throws SQLException {
 			StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("SELECT 1").get(0);
 			FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("firebolt1")
 					.ssl(true).compress(false).build();
-			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, true);
-			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, 10, 10, true,
+			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
+			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, 10, 10, true, true,
 					mock(FireboltStatement.class));
 			Assertions.assertEquals(1, mocked.constructed().size());
 			verify(statementClient).executeSqlStatement(statementInfoWrapper, fireboltProperties, true, 10, 10, true);
@@ -100,8 +100,8 @@ void shouldIncludeNonStandardSqlQueryParamForNonStandardSql() throws SQLExceptio
 			FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("localhost")
 					.ssl(true).compress(false).build();
 
-			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, true);
-			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, -1, 0, false,
+			FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
+			fireboltStatementService.execute(statementInfoWrapper, fireboltProperties, -1, 0, false, true,
 					mock(FireboltStatement.class));
 			Assertions.assertEquals(1, mocked.constructed().size());
 			verify(statementClient).executeSqlStatement(statementInfoWrapper, fireboltProperties, true, -1, 0, false);
@@ -115,9 +115,9 @@ void shouldBeEmptyWithNonQueryStatement() throws SQLException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db").host("localhost").ssl(true)
 				.compress(false).build();
 
-		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient, false);
+		FireboltStatementService fireboltStatementService = new FireboltStatementService(statementClient);
 		Assertions.assertEquals(Optional.empty(), fireboltStatementService.execute(statementInfoWrapper,
-				fireboltProperties, -1, 10, true, mock(FireboltStatement.class)));
+				fireboltProperties, -1, 10, true, false, mock(FireboltStatement.class)));
 		verify(statementClient).executeSqlStatement(statementInfoWrapper, fireboltProperties, false, -1, 10, true);
 	}
 
diff --git a/src/test/java/com/firebolt/jdbc/statement/FireboltStatementTest.java b/src/test/java/com/firebolt/jdbc/statement/FireboltStatementTest.java
index 325e4aa8f..a2232287b 100644
--- a/src/test/java/com/firebolt/jdbc/statement/FireboltStatementTest.java
+++ b/src/test/java/com/firebolt/jdbc/statement/FireboltStatementTest.java
@@ -76,9 +76,9 @@ void shouldCloseInputStreamOnClose() throws SQLException {
 		FireboltStatement fireboltStatement = FireboltStatement.builder().statementService(fireboltStatementService)
 				.sessionProperties(fireboltProperties).connection(connection).build();
 
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.empty());
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.of(rs));
 		fireboltStatement.executeQuery("show database");
 		fireboltStatement.close();
@@ -106,11 +106,11 @@ void shouldExecuteIfUpdateStatementWouldNotReturnAResultSet() throws SQLExceptio
 		try (FireboltStatement fireboltStatement = FireboltStatement.builder()
 				.statementService(fireboltStatementService).connection(fireboltConnection)
 				.sessionProperties(fireboltProperties).build()) {
-			when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+			when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 					.thenReturn(Optional.empty());
 			assertEquals(0, fireboltStatement.executeUpdate("INSERT INTO cars(sales, name) VALUES (500, 'Ford')"));
 			verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(fireboltProperties),
-					anyInt(), anyInt(), anyBoolean(), any());
+					anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 			assertEquals("INSERT INTO cars(sales, name) VALUES (500, 'Ford')",
 					queryInfoWrapperArgumentCaptor.getValue().getSql());
 			assertEquals(0, fireboltStatement.getUpdateCount());
@@ -128,7 +128,7 @@ void shouldCloseCurrentAndGetMoreResultsForMultiStatementQuery() throws SQLExcep
 		FireboltStatement fireboltStatement = FireboltStatement.builder().statementService(fireboltStatementService)
 				.sessionProperties(fireboltProperties).connection(connection).build();
 
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.of(rs)).thenReturn(Optional.of(rs2));
 		fireboltStatement.execute("SELECT 1; SELECT 2;");
 		assertEquals(rs, fireboltStatement.getResultSet());
@@ -150,7 +150,7 @@ void shouldCloseCurrentAndGetMoreResultWhenCallingGetMoreResultsWithCloseCurrent
 				.build();
 		FireboltStatement fireboltStatement = FireboltStatement.builder().statementService(fireboltStatementService)
 				.sessionProperties(fireboltProperties).connection(connection).build();
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.of(mock(FireboltResultSet.class)));
 		fireboltStatement.execute("SELECT 1; SELECT 2;");
 		ResultSet resultSet = fireboltStatement.getResultSet();
@@ -165,7 +165,7 @@ void shouldKeepCurrentAndGetMoreResultWhenCallingGetMoreResultsWithKeepCurrentRe
 				.build();
 		FireboltStatement fireboltStatement = FireboltStatement.builder().statementService(fireboltStatementService)
 				.sessionProperties(fireboltProperties).connection(connection).build();
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.of(mock(ResultSet.class)));
 
 		fireboltStatement.execute("SELECT 1; SELECT 2;");
@@ -185,7 +185,7 @@ void shouldCloseUnclosedAndGetMoreResultWhenCallingGetMoreResultsWithCloseAllRes
 		FireboltStatement fireboltStatement = FireboltStatement.builder().statementService(fireboltStatementService)
 				.sessionProperties(fireboltProperties).connection(connection).build();
 
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.of(rs)).thenReturn(Optional.of(rs2)).thenReturn(Optional.of(rs3));
 
 		fireboltStatement.execute("SELECT 1; SELECT 2; SELECT 3;");
diff --git a/src/test/java/com/firebolt/jdbc/statement/preparedstatement/FireboltPreparedStatementTest.java b/src/test/java/com/firebolt/jdbc/statement/preparedstatement/FireboltPreparedStatementTest.java
index 35aa73073..95da31bc7 100644
--- a/src/test/java/com/firebolt/jdbc/statement/preparedstatement/FireboltPreparedStatementTest.java
+++ b/src/test/java/com/firebolt/jdbc/statement/preparedstatement/FireboltPreparedStatementTest.java
@@ -42,7 +42,7 @@ class FireboltPreparedStatementTest {
 	@BeforeEach
 	void beforeEach() throws SQLException {
 		lenient().when(properties.getBufferSize()).thenReturn(10);
-		lenient().when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), any()))
+		lenient().when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.empty());
 	}
 
@@ -56,7 +56,7 @@ void shouldExecute() throws SQLException {
 		statement.setObject(2, "Ford");
 		statement.execute();
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 
 		assertEquals("INSERT INTO cars (sales, make) VALUES (500,'Ford')",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
@@ -76,7 +76,7 @@ void shouldExecuteBatch() throws SQLException {
 		statement.addBatch();
 		statement.executeBatch();
 		verify(fireboltStatementService, times(2)).execute(queryInfoWrapperArgumentCaptor.capture(),
-				eq(this.properties), anyInt(), anyInt(), anyBoolean(), any());
+				eq(this.properties), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 
 		assertEquals("INSERT INTO cars (sales, make) VALUES (150,'Ford')",
 				queryInfoWrapperArgumentCaptor.getAllValues().get(0).getSql());
@@ -113,7 +113,7 @@ void shouldExecuteWithSpecialCharactersInQuery() throws SQLException {
 
 		statement.execute();
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals(expectedSql, queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
 
@@ -149,7 +149,7 @@ void shouldSetNull() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("INSERT INTO cars (sales, make) VALUES (\\N,\\N)",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
@@ -162,7 +162,7 @@ void shouldSetBoolean() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("INSERT INTO cars(available) VALUES (1)", queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
 
@@ -186,7 +186,7 @@ void shouldSetInt() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 	}
 
 	@Test
@@ -197,7 +197,7 @@ void shouldSetLong() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("INSERT INTO cars(price) VALUES (50)", queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
 
@@ -209,7 +209,7 @@ void shouldSetFloat() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 
 		assertEquals("INSERT INTO cars(price) VALUES (5.5)", queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
@@ -222,7 +222,7 @@ void shouldSetDouble() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 	}
 
 	@Test
@@ -233,7 +233,7 @@ void shouldSetBigDecimal() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("INSERT INTO cars(price) VALUES (555555555555.55555555)",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
@@ -247,7 +247,7 @@ void shouldSetDate() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 		assertEquals("INSERT INTO cars(release_date) VALUES ('2019-07-31')",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
 	}
@@ -261,7 +261,7 @@ void shouldSetTimeStamp() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 
 		assertEquals("INSERT INTO cars(release_date) VALUES ('2019-07-31 12:15:13')",
 				queryInfoWrapperArgumentCaptor.getValue().getSql());
@@ -286,7 +286,7 @@ void shouldSetAllObjects() throws SQLException {
 		statement.execute();
 
 		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), eq(this.properties),
-				anyInt(), anyInt(), anyBoolean(), any());
+				anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
 
 		assertEquals(
 				"INSERT INTO cars(timestamp, date, float, long, big_decimal, null, boolean, int) VALUES ('2019-07-31 12:15:13','2019-07-31',5.5,5,555555555555.55555555,\\N,1,5)",
diff --git a/src/test/java/com/firebolt/jdbc/util/PropertyUtilTest.java b/src/test/java/com/firebolt/jdbc/util/PropertyUtilTest.java
index bc2aadfa5..e64869d4b 100644
--- a/src/test/java/com/firebolt/jdbc/util/PropertyUtilTest.java
+++ b/src/test/java/com/firebolt/jdbc/util/PropertyUtilTest.java
@@ -1,5 +1,6 @@
 package com.firebolt.jdbc.util;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mockStatic;
 
@@ -23,14 +24,14 @@ void shouldGetPropertyInfo() {
 					FireboltSessionProperty.BUFFER_SIZE);
 			mocked.when(FireboltSessionProperty::getNonDeprecatedProperties).thenReturn(existingProperties);
 			DriverPropertyInfo accountDriverInfo = createExpectedDriverInfo(FireboltSessionProperty.ACCOUNT.getKey(),
-					FireboltSessionProperty.ACCOUNT.getDescription(), null);
+					FireboltSessionProperty.ACCOUNT.getDescription(), "myAccount");
 			DriverPropertyInfo bufferDriverInfo = createExpectedDriverInfo(FireboltSessionProperty.BUFFER_SIZE.getKey(),
 					FireboltSessionProperty.BUFFER_SIZE.getDescription(), "1");
 			DriverPropertyInfo[] expected = new DriverPropertyInfo[] { accountDriverInfo, bufferDriverInfo };
 
 			for (int i = 0; i < expected.length; i++) {
 				assertTrue(new ReflectionEquals(
-						PropertyUtil.getPropertyInfo("jdbc:firebolt://api.dev.firebolt.io/Tutorial_11_04?buffer_size=1",
+						PropertyUtil.getPropertyInfo("jdbc:firebolt:Tutorial_11_04/?buffer_size=1&account=myAccount",
 								new Properties())[i]).matches(expected[i]));
 			}
 		}

From d7533e36a66f724dc89176c9341a8b345ad9d074 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Thu, 6 Jul 2023 18:31:57 +0300
Subject: [PATCH 02/15] fixed implementation of new identity

---
 .../java/integration/ConnectionInfo.java      |  58 ++-
 .../java/integration/IntegrationTest.java     |  14 +-
 .../java/com/firebolt/FireboltDriver.java     |   8 +-
 .../jdbc/client/account/FireboltAccount.java  |  40 ++
 .../account/FireboltAccountRetriever.java     |  31 ++
 .../ServiceAccountAuthenticationRequest.java  |  15 +-
 .../gateway/FireboltGatewayUrlClient.java     |  38 --
 .../client/query/StatementClientImpl.java     |  76 ++--
 .../jdbc/connection/FireboltConnection.java   | 109 +++---
 .../com/firebolt/jdbc/connection/UrlUtil.java |  17 +
 .../settings/FireboltProperties.java          |  26 +-
 .../settings/FireboltQueryParameterKey.java   |   9 +-
 .../settings/FireboltSessionProperty.java     |   5 +-
 .../metadata/FireboltDatabaseMetadata.java    |   2 +-
 .../service/FireboltAccountIdService.java     |  17 +
 .../FireboltAuthenticationService.java        |  61 ++-
 .../jdbc/service/FireboltEngineService.java   |  83 ++---
 .../service/FireboltGatewayUrlService.java    |   7 +-
 .../account/FireboltAccountClientTest.java    | 209 -----------
 ...rviceAccountAuthenticationRequestTest.java |   5 +-
 .../gateway/FireboltGatewayUrlClientTest.java |  77 ++--
 .../client/query/StatementClientImplTest.java |   4 +-
 .../connection/FireboltConnectionTest.java    | 352 +++++++++---------
 .../settings/FireboltPropertiesTest.java      |   4 +-
 .../FireboltAuthenticationServiceTest.java    |   3 +-
 .../service/FireboltEngineServiceTest.java    |  53 ++-
 26 files changed, 600 insertions(+), 723 deletions(-)
 create mode 100644 src/main/java/com/firebolt/jdbc/client/account/FireboltAccount.java
 create mode 100644 src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
 delete mode 100644 src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
 create mode 100644 src/main/java/com/firebolt/jdbc/service/FireboltAccountIdService.java
 delete mode 100644 src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java

diff --git a/src/integrationTest/java/integration/ConnectionInfo.java b/src/integrationTest/java/integration/ConnectionInfo.java
index f4ea57ded..d9d527eeb 100644
--- a/src/integrationTest/java/integration/ConnectionInfo.java
+++ b/src/integrationTest/java/integration/ConnectionInfo.java
@@ -1,31 +1,59 @@
 package integration;
 
-import lombok.Value;
-
 import java.util.Optional;
 
-@Value
+import static java.lang.System.getProperty;
+
 public class ConnectionInfo {
-	private static ConnectionInfo INSTANCE;
-	String password;
-	String user;
-	String env;
-	String database;
-	String account;
+	private static volatile ConnectionInfo INSTANCE;
+	private final String principal;
+	private final String secret;
+	private final String env;
+	private final String database;
+	private final String account;
+	private final String engine;
 
 	private ConnectionInfo() {
-		password = Optional.ofNullable(System.getProperty("password")).map(p -> p.replace("\"", "")).orElse(null);
-		user = Optional.ofNullable(System.getProperty("user")).map(u -> u.replace("\"", "")).orElse(null);
-		env = System.getProperty("env");
-		database = System.getProperty("db");
-		account = System.getProperty("account");
+		principal = Optional.ofNullable(getProperty("client_id", getProperty("user"))).map(u -> u.replace("\"", "")).orElse(null);
+		secret = Optional.ofNullable(getProperty("client_secret", getProperty("password"))).map(p -> p.replace("\"", "")).orElse(null);
+		env = getProperty("env");
+		database = getProperty("db");
+		account = getProperty("account");
+		engine = getProperty("engine");
 	}
 
 	public static ConnectionInfo getInstance() {
 		if (INSTANCE == null) {
-			INSTANCE = new ConnectionInfo();
+			synchronized (ConnectionInfo.class) {
+				if (INSTANCE == null) {
+					INSTANCE = new ConnectionInfo();
+				}
+			}
 		}
 		return INSTANCE;
 	}
 
+	public String getPrincipal() {
+		return principal;
+	}
+
+	public String getSecret() {
+		return secret;
+	}
+
+	public String getEnv() {
+		return env;
+	}
+
+	public String getDatabase() {
+		return database;
+	}
+
+	public String getAccount() {
+		return account;
+	}
+
+	public String getEngine() {
+		return engine;
+	}
 }
diff --git a/src/integrationTest/java/integration/IntegrationTest.java b/src/integrationTest/java/integration/IntegrationTest.java
index 29c0a6ebb..a66eba9d4 100644
--- a/src/integrationTest/java/integration/IntegrationTest.java
+++ b/src/integrationTest/java/integration/IntegrationTest.java
@@ -26,16 +26,16 @@ protected Connection createLocalConnection(String queryParams) throws SQLExcepti
 		return DriverManager.getConnection(
 				JDBC_URL_PREFIX + integration.ConnectionInfo.getInstance().getDatabase()
 						+ queryParams + "&host=localhost" + getAccountParam(),
-				integration.ConnectionInfo.getInstance().getUser(),
-				integration.ConnectionInfo.getInstance().getPassword());
+				integration.ConnectionInfo.getInstance().getPrincipal(),
+				integration.ConnectionInfo.getInstance().getSecret());
 	}
 
 	protected Connection createConnection() throws SQLException {
 		return DriverManager.getConnection(
 				JDBC_URL_PREFIX
 						+ integration.ConnectionInfo.getInstance().getDatabase() + "?" + getEnvParam() + getAccountParam() ,
-				integration.ConnectionInfo.getInstance().getUser(),
-				integration.ConnectionInfo.getInstance().getPassword());
+				integration.ConnectionInfo.getInstance().getPrincipal(),
+				integration.ConnectionInfo.getInstance().getSecret());
 	}
 
 	protected Connection createConnection(String engine) throws SQLException {
@@ -43,8 +43,8 @@ protected Connection createConnection(String engine) throws SQLException {
 				JDBC_URL_PREFIX +
 						 integration.ConnectionInfo.getInstance().getDatabase()
 						+ Optional.ofNullable(engine).map(e -> "?" + getEnvParam() +"&engine=" + e + getAccountParam() ).orElse("?" + getEnvParam() + getAccountParam()),
-				integration.ConnectionInfo.getInstance().getUser(),
-				integration.ConnectionInfo.getInstance().getPassword());
+				integration.ConnectionInfo.getInstance().getPrincipal(),
+				integration.ConnectionInfo.getInstance().getSecret());
 	}
 
 	protected void setParam(Connection connection, String name, String value) throws SQLException {
@@ -55,7 +55,7 @@ protected void setParam(Connection connection, String name, String value) throws
 
 	@SneakyThrows
 	protected void executeStatementFromFile(String path) {
-		executeStatementFromFile(path, null);
+		executeStatementFromFile(path, integration.ConnectionInfo.getInstance().getEngine());
 	}
 
 	@SneakyThrows
diff --git a/src/main/java/com/firebolt/FireboltDriver.java b/src/main/java/com/firebolt/FireboltDriver.java
index 849e59adb..15e248c1b 100644
--- a/src/main/java/com/firebolt/FireboltDriver.java
+++ b/src/main/java/com/firebolt/FireboltDriver.java
@@ -30,11 +30,7 @@ public class FireboltDriver implements Driver {
 
 	@Override
 	public Connection connect(String url, Properties connectionSettings) throws SQLException {
-		if (!acceptsURL(url)) {
-			return null;
-		} else {
-			return new FireboltConnection(url, connectionSettings);
-		}
+		return acceptsURL(url) ? new FireboltConnection(url, connectionSettings) : null;
 	}
 
 	@Override
@@ -43,7 +39,7 @@ public boolean acceptsURL(String url) {
 	}
 
 	@Override
-	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
 		return PropertyUtil.getPropertyInfo(url, info);
 	}
 
diff --git a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccount.java b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccount.java
new file mode 100644
index 000000000..31a94c90c
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccount.java
@@ -0,0 +1,40 @@
+package com.firebolt.jdbc.client.account;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.Objects;
+
+public class FireboltAccount {
+    @JsonProperty
+    private final String id;
+    @JsonProperty
+    private final String region;
+
+    @JsonCreator
+    public FireboltAccount(@JsonProperty("id") String id, @JsonProperty("region") String region) {
+        this.id = id;
+        this.region = region;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        FireboltAccount account = (FireboltAccount) o;
+        return Objects.equals(id, account.id) && Objects.equals(region, account.region);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, region);
+    }
+}
diff --git a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
new file mode 100644
index 000000000..cc7936877
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
@@ -0,0 +1,31 @@
+package com.firebolt.jdbc.client.account;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.firebolt.jdbc.client.FireboltClient;
+import com.firebolt.jdbc.connection.FireboltConnection;
+import com.firebolt.jdbc.exception.FireboltException;
+import okhttp3.OkHttpClient;
+
+import java.io.IOException;
+
+import static java.lang.String.format;
+
+public class FireboltAccountRetriever<T> extends FireboltClient {
+    private static final String URL = "https://api.dev.firebolt.io/web/v3/account/%s/%s";
+    private final String path;
+    private final Class<T> type;
+
+    public FireboltAccountRetriever(OkHttpClient httpClient, FireboltConnection connection, String customDrivers, String customClients, ObjectMapper objectMapper, String path, Class<T> type) {
+        super(httpClient, connection, customDrivers, customClients, objectMapper);
+        this.path = path;
+        this.type = type;
+    }
+
+    public T retrieve(String accessToken, String accountName) throws FireboltException {
+        try {
+            return getResource(format(URL, accountName, path), accessToken, type);
+        } catch (IOException e) {
+            throw new FireboltException(String.format("Failed to get %s url for account %s", path, accountName), e);
+        }
+    }
+}
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java b/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
index 4819bbc6a..50ca3e569 100644
--- a/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
+++ b/src/main/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequest.java
@@ -1,14 +1,12 @@
 package com.firebolt.jdbc.client.authentication;
 
-import com.fasterxml.jackson.core.JsonProcessingException;
-import lombok.AllArgsConstructor;
 import okhttp3.FormBody;
 import okhttp3.RequestBody;
 
-@AllArgsConstructor
 public class ServiceAccountAuthenticationRequest implements AuthenticationRequest {
 
     private static final String AUDIENCE_FIELD_NAME = "audience";
+    private static final String AUDIENCE_FIELD_VALUE = "https://api.firebolt.io";
     private static final String GRAND_TYPE_FIELD_NAME = "grant_type";
     private static final String GRAND_TYPE_FIELD_VALUE = "client_credentials";
     private static final String CLIENT_ID_FIELD_NAME = "client_id";
@@ -19,9 +17,16 @@ public class ServiceAccountAuthenticationRequest implements AuthenticationReques
     private final String clientSecret;
     private final String environment;
 
+    public ServiceAccountAuthenticationRequest(String clientId, String clientSecret, String environment) {
+        this.clientId = clientId;
+        this.clientSecret = clientSecret;
+        this.environment = environment;
+    }
+
     @Override
-    public RequestBody getRequestBody() throws JsonProcessingException {
-        return new FormBody.Builder().add(AUDIENCE_FIELD_NAME, String.format("https://%s-firebolt-v2.us.auth0.com/api/v2/", environment))
+    public RequestBody getRequestBody() {
+        return new FormBody.Builder()
+                .add(AUDIENCE_FIELD_NAME, AUDIENCE_FIELD_VALUE)
                 .add(GRAND_TYPE_FIELD_NAME, GRAND_TYPE_FIELD_VALUE)
                 .add(CLIENT_ID_FIELD_NAME, clientId)
                 .add(CLIENT_SECRET_FIELD_NAME, clientSecret).build();
diff --git a/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java b/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
deleted file mode 100644
index e65850cbd..000000000
--- a/src/main/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClient.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.firebolt.jdbc.client.gateway;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.firebolt.jdbc.client.FireboltClient;
-import com.firebolt.jdbc.connection.FireboltConnection;
-import com.firebolt.jdbc.exception.FireboltException;
-import lombok.CustomLog;
-import okhttp3.OkHttpClient;
-
-@CustomLog
-public class FireboltGatewayUrlClient extends FireboltClient {
-
-    private static final String URL = "https://api.dev.firebolt.io/web/v3/account/%s/engineUrl";
-
-    public FireboltGatewayUrlClient(OkHttpClient httpClient, ObjectMapper objectMapper,
-                                    FireboltConnection fireboltConnection, String customDrivers, String customClients) {
-        super(httpClient, fireboltConnection, customDrivers, customClients, objectMapper);
-    }
-
-    /**
-     * Returns the gateway URL
-     *
-     * @param accessToken the access token
-     * @return the account
-     */
-    public GatewayUrlResponse getGatewayUrl(String accessToken, String account)
-            throws FireboltException {
-        String url = String.format(URL, account);
-        try {
-            return getResource(url, accessToken, GatewayUrlResponse.class);
-        } catch (FireboltException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new FireboltException(String.format("Failed to get gateway url for account %s", account), e);
-        }
-    }
-
-}
diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index 7e6d8563f..b23464ca9 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -1,17 +1,5 @@
 package com.firebolt.jdbc.client.query;
 
-import static com.firebolt.jdbc.exception.ExceptionType.UNAUTHORIZED;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.*;
-import java.util.function.BiPredicate;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.ImmutablePair;
-import org.apache.commons.lang3.tuple.Pair;
-
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.firebolt.jdbc.client.FireboltClient;
 import com.firebolt.jdbc.connection.FireboltConnection;
@@ -24,12 +12,24 @@
 import com.firebolt.jdbc.statement.rawstatement.RawStatement;
 import com.firebolt.jdbc.util.CloseableUtil;
 import com.firebolt.jdbc.util.PropertyUtil;
-import com.google.common.collect.ImmutableMap;
-
 import lombok.CustomLog;
 import lombok.NonNull;
 import okhttp3.*;
 import okhttp3.internal.http2.StreamResetException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.*;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+
+import static com.firebolt.jdbc.connection.settings.FireboltQueryParameterKey.DEFAULT_FORMAT;
+import static com.firebolt.jdbc.connection.settings.FireboltQueryParameterKey.OUTPUT_FORMAT;
+import static com.firebolt.jdbc.exception.ExceptionType.UNAUTHORIZED;
+import static java.lang.String.format;
 
 @CustomLog
 public class StatementClientImpl extends FireboltClient implements StatementClient {
@@ -68,12 +68,11 @@ public InputStream executeSqlStatement(@NonNull StatementInfoWrapper statementIn
 				queryTimeout, maxRows);
 		try {
 			String uri = this.buildQueryUri(connectionProperties, params).toString();
-			return executeSqlStatementWithRetryOnUnauthorized(statementInfoWrapper, connectionProperties,
-					formattedStatement, uri);
+			return executeSqlStatementWithRetryOnUnauthorized(statementInfoWrapper, connectionProperties, formattedStatement, uri);
 		} catch (FireboltException e) {
 			throw e;
 		} catch (Exception e) {
-			String errorMessage = String.format("Error executing statement with id %s: %s",
+			String errorMessage = format("Error executing statement with id %s: %s",
 					statementInfoWrapper.getId(), formattedStatement);
 			if (e instanceof StreamResetException) {
 				throw new FireboltException(errorMessage, e, ExceptionType.CANCELED);
@@ -145,8 +144,7 @@ public void abortStatement(String id, FireboltProperties fireboltProperties) thr
 				throw e;
 			}
 		} catch (Exception e) {
-			throw new FireboltException(
-					String.format("Could not cancel query: %s at %s", id, fireboltProperties.getHost()), e);
+			throw new FireboltException(format("Could not cancel query: %s at %s", id, fireboltProperties.getHost()), e);
 		}
 	}
 
@@ -161,13 +159,15 @@ public void abortRunningHttpRequest(@NonNull String id) {
 	}
 
 	private Optional<Call> getQueuedCallWithId(String id) {
-		return getHttpClient().dispatcher().queuedCalls().stream().filter(call -> isCallWithId.test(call, id))
-				.findAny();
+		return getSelectedCallWithId(id, Dispatcher::queuedCalls);
 	}
 
 	private Optional<Call> getRunningCallWithId(String id) {
-		return getHttpClient().dispatcher().runningCalls().stream().filter(call -> isCallWithId.test(call, id))
-				.findAny();
+		return getSelectedCallWithId(id, Dispatcher::runningCalls);
+	}
+
+	private Optional<Call> getSelectedCallWithId(String id, Function<Dispatcher, List<Call>> callsGetter) {
+		return callsGetter.apply(getHttpClient().dispatcher()).stream().filter(call -> isCallWithId.test(call, id)).findAny();
 	}
 
 	@Override
@@ -176,7 +176,7 @@ public boolean isStatementRunning(String statementId) {
 	}
 
 	private URI buildQueryUri(FireboltProperties fireboltProperties, Map<String, String> parameters) {
-		return buildURI(fireboltProperties, parameters, PropertyUtil.isLocalDb(fireboltProperties) ? Collections.emptyList() : URI_QUERY_SEGMENTS);
+		return buildURI(fireboltProperties, parameters, PropertyUtil.isLocalDb(fireboltProperties) || !fireboltProperties.isSystemEngine() ? Collections.emptyList() : URI_QUERY_SEGMENTS);
 	}
 
 	private URI buildCancelUri(FireboltProperties fireboltProperties, String id) {
@@ -187,8 +187,9 @@ private URI buildCancelUri(FireboltProperties fireboltProperties, String id) {
 	private URI buildURI(FireboltProperties fireboltProperties, Map<String, String> parameters,
 			List<String> pathSegments) {
 		HttpUrl.Builder httpUrlBuilder = new HttpUrl.Builder()
-				.scheme(Boolean.TRUE.equals(fireboltProperties.isSsl()) ? "https" : "http")
-				.host(fireboltProperties.getHost()).port(fireboltProperties.getPort());
+				.scheme(fireboltProperties.isSsl() ? "https" : "http")
+				.host(fireboltProperties.getHost())
+				.port(fireboltProperties.getPort());
 		parameters.forEach(httpUrlBuilder::addQueryParameter);
 
 		pathSegments.forEach(httpUrlBuilder::addPathSegment);
@@ -204,12 +205,13 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 
 		getResponseFormatParameter(statementInfoWrapper.getType() == StatementType.QUERY, isLocalDb)
 				.ifPresent(format -> params.put(format.getLeft(), format.getRight()));
-		// System engines do not support the following query params
-		if (!systemEngine) {
+		if (systemEngine) {
+			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId()); // "01h11x0zmecanh1vp2q1mar5nh"
+		} else {
+			// System engines do not support the following query params
 			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
 			params.put(FireboltQueryParameterKey.QUERY_ID.getKey(), statementInfoWrapper.getId());
-			params.put(FireboltQueryParameterKey.COMPRESS.getKey(),
-					String.format("%d", fireboltProperties.isCompress() ? 1 : 0));
+			params.put(FireboltQueryParameterKey.COMPRESS.getKey(), fireboltProperties.isCompress() ? "1" : "0");
 
 			if (queryTimeout > -1) {
 				params.put("max_execution_time", String.valueOf(queryTimeout));
@@ -224,20 +226,10 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 	}
 
 	private Optional<Pair<String, String>> getResponseFormatParameter(boolean isQuery, boolean isLocalDb) {
-		if (isQuery) {
-			if (isLocalDb) {
-				return Optional.of(new ImmutablePair<>(FireboltQueryParameterKey.DEFAULT_FORMAT.getKey(),
-						TAB_SEPARATED_WITH_NAMES_AND_TYPES_FORMAT));
-			} else {
-				return Optional.of(new ImmutablePair<>(FireboltQueryParameterKey.OUTPUT_FORMAT.getKey(),
-						TAB_SEPARATED_WITH_NAMES_AND_TYPES_FORMAT));
-			}
-		}
-		return Optional.empty();
+		return isQuery ? Optional.of(Pair.of((isLocalDb ? DEFAULT_FORMAT : OUTPUT_FORMAT).getKey(), TAB_SEPARATED_WITH_NAMES_AND_TYPES_FORMAT)) : Optional.empty();
 	}
 
 	private Map<String, String> getCancelParameters(String statementId) {
-		return ImmutableMap.of(FireboltQueryParameterKey.QUERY_ID.getKey(), statementId);
+		return Map.of(FireboltQueryParameterKey.QUERY_ID.getKey(), statementId);
 	}
-
 }
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index 4493d3f54..26acdcd3d 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -1,31 +1,14 @@
 package com.firebolt.jdbc.connection;
 
-import static com.firebolt.jdbc.connection.settings.FireboltProperties.SYSTEM_ENGINE_NAME;
-import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
-
-import java.io.IOException;
-import java.net.URI;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.sql.*;
-import java.util.*;
-import java.util.concurrent.Executor;
-
-import com.firebolt.jdbc.client.gateway.FireboltGatewayUrlClient;
-import com.firebolt.jdbc.service.FireboltEngineService;
-import com.firebolt.jdbc.service.FireboltGatewayUrlService;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-
 import com.fasterxml.jackson.databind.ObjectMapper;
-import com.firebolt.jdbc.util.PropertyUtil;
 import com.firebolt.jdbc.annotation.ExcludeFromJacocoGeneratedReport;
 import com.firebolt.jdbc.annotation.NotImplemented;
 import com.firebolt.jdbc.client.FireboltObjectMapper;
 import com.firebolt.jdbc.client.HttpClientConfig;
+import com.firebolt.jdbc.client.account.FireboltAccount;
+import com.firebolt.jdbc.client.account.FireboltAccountRetriever;
 import com.firebolt.jdbc.client.authentication.FireboltAuthenticationClient;
+import com.firebolt.jdbc.client.gateway.GatewayUrlResponse;
 import com.firebolt.jdbc.client.query.StatementClientImpl;
 import com.firebolt.jdbc.connection.settings.FireboltProperties;
 import com.firebolt.jdbc.exception.ExceptionType;
@@ -34,24 +17,33 @@
 import com.firebolt.jdbc.exception.FireboltUnsupportedOperationException;
 import com.firebolt.jdbc.metadata.FireboltDatabaseMetadata;
 import com.firebolt.jdbc.metadata.FireboltSystemEngineDatabaseMetadata;
-import com.firebolt.jdbc.service.FireboltAuthenticationService;
-import com.firebolt.jdbc.service.FireboltStatementService;
+import com.firebolt.jdbc.service.*;
 import com.firebolt.jdbc.statement.FireboltStatement;
 import com.firebolt.jdbc.statement.preparedstatement.FireboltPreparedStatement;
-
+import com.firebolt.jdbc.util.PropertyUtil;
 import lombok.CustomLog;
 import lombok.NonNull;
 import okhttp3.OkHttpClient;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.Executor;
+
+import static com.firebolt.jdbc.connection.settings.FireboltProperties.SYSTEM_ENGINE_NAME;
+import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
 
 @CustomLog
 public class FireboltConnection implements Connection {
 
 	private final FireboltAuthenticationService fireboltAuthenticationService;
 	private final FireboltStatementService fireboltStatementService;
-
 	private final FireboltEngineService fireboltEngineService;
-
 	private final FireboltGatewayUrlService fireboltGatewayUrlService;
+	private final FireboltAccountIdService fireboltAccountIdService;
 	private final String httpConnectionUrl;
 	private final List<FireboltStatement> statements;
 	private final int connectionTimeout;
@@ -65,46 +57,53 @@ public class FireboltConnection implements Connection {
 	private final FireboltProperties loginProperties;
 
 	public FireboltConnection(@NonNull String url, Properties connectionSettings,
-			FireboltAuthenticationService fireboltAuthenticationService,
-			FireboltGatewayUrlService fireboltGatewayUrlService, FireboltStatementService fireboltStatementService, FireboltEngineService fireboltEngineService) throws FireboltException {
+							  FireboltAuthenticationService fireboltAuthenticationService,
+							  FireboltGatewayUrlService fireboltGatewayUrlService,
+							  FireboltStatementService fireboltStatementService,
+							  FireboltEngineService fireboltEngineService,
+							  FireboltAccountIdService fireboltAccountIdService) throws FireboltException {
+		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
+
 		this.fireboltAuthenticationService = fireboltAuthenticationService;
 		this.fireboltGatewayUrlService = fireboltGatewayUrlService;
-		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
 		this.httpConnectionUrl = getHttpConnectionUrl(loginProperties);
 		this.fireboltStatementService = fireboltStatementService;
+
 		this.statements = new ArrayList<>();
 		this.connectionTimeout = loginProperties.getConnectionTimeoutMillis();
 		this.networkTimeout = loginProperties.getSocketTimeoutMillis();
 		this.systemEngine = loginProperties.isSystemEngine();
 		this.fireboltEngineService = fireboltEngineService;
+		this.fireboltAccountIdService = fireboltAccountIdService;
 		this.connect();
 	}
 
+	// This ugly code duplication between constructors is done because of back reference: dependent services require reference to current instance of FireboltConnection that prevents using constructor chaining or factory method.
 	@ExcludeFromJacocoGeneratedReport
 	public FireboltConnection(@NonNull String url, Properties connectionSettings) throws FireboltException {
+		this.loginProperties = extractFireboltProperties(url, connectionSettings);
+		OkHttpClient httpClient = getHttpClient(loginProperties);
 		ObjectMapper objectMapper = FireboltObjectMapper.getInstance();
-		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
+
+		this.fireboltAuthenticationService = new FireboltAuthenticationService(new FireboltAuthenticationClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
+		this.fireboltGatewayUrlService = new FireboltGatewayUrlService(new FireboltAccountRetriever<>(httpClient, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), objectMapper, "engineUrl", GatewayUrlResponse.class));
 		this.httpConnectionUrl = getHttpConnectionUrl(loginProperties);
-		OkHttpClient httpClient = getHttpClient(loginProperties);
-		this.systemEngine = loginProperties.isSystemEngine();
-		this.fireboltGatewayUrlService = new FireboltGatewayUrlService(new FireboltGatewayUrlClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
-		this.fireboltAuthenticationService = new FireboltAuthenticationService(
-				new FireboltAuthenticationClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
-		this.fireboltEngineService = new FireboltEngineService(this);
-		this.fireboltStatementService = new FireboltStatementService(
-				new StatementClientImpl(httpClient, this, objectMapper, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
+		this.fireboltStatementService = new FireboltStatementService(new StatementClientImpl(httpClient, this, objectMapper, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
+
 		this.statements = new ArrayList<>();
 		this.connectionTimeout = loginProperties.getConnectionTimeoutMillis();
 		this.networkTimeout = loginProperties.getSocketTimeoutMillis();
+		this.systemEngine = loginProperties.isSystemEngine();
+		this.fireboltEngineService = new FireboltEngineService(this);
+		this.fireboltAccountIdService = new FireboltAccountIdService(new FireboltAccountRetriever<>(httpClient, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), objectMapper, "resolve", FireboltAccount.class));
+
 		this.connect();
 	}
 
 	private static OkHttpClient getHttpClient(FireboltProperties fireboltProperties) throws FireboltException {
 		try {
-			return HttpClientConfig.getInstance() == null ? HttpClientConfig.init(fireboltProperties)
-					: HttpClientConfig.getInstance();
-		} catch (CertificateException | NoSuchAlgorithmException | KeyStoreException | KeyManagementException
-				| IOException e) {
+			return HttpClientConfig.getInstance() == null ? HttpClientConfig.init(fireboltProperties) : HttpClientConfig.getInstance();
+		} catch (GeneralSecurityException | IOException e) {
 			throw new FireboltException("Could not instantiate http client", e);
 		}
 	}
@@ -113,12 +112,18 @@ private void connect() throws FireboltException {
 		String accessToken = this.getAccessToken(loginProperties).orElse(StringUtils.EMPTY);
 		closed = false;
 		if (!PropertyUtil.isLocalDb(loginProperties)) {
-			internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, this.loginProperties.getAccount());
-			if (!this.loginProperties.isSystemEngine()) {
+			internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, loginProperties.getAccount());
+			String accountId =  fireboltAccountIdService.getValue(accessToken, loginProperties.getAccount());
+			if (!loginProperties.isSystemEngine()) {
+				sessionProperties = internalSystemEngineProperties.toBuilder()
+						.engine(loginProperties.getEngine())
+						.systemEngine(true)
+						.accountId(accountId)
+						.build();
 				sessionProperties = getSessionPropertiesForNonSystemEngine();
 			} else {
 				//When using system engine, the system engine properties are the same as the session properties
-				sessionProperties = internalSystemEngineProperties.toBuilder().build();
+				sessionProperties = internalSystemEngineProperties.toBuilder().accountId(accountId).build();
 			}
 		} else {
 			//When running packdb locally, the login properties are the session properties
@@ -127,13 +132,9 @@ private void connect() throws FireboltException {
 		log.debug("Connection opened");
 	}
 
-	private FireboltProperties getSessionPropertiesForNonSystemEngine() {
-
-/*		This is currently not supported
-		Engine engine = fireboltEngineService.getEngine(this.loginProperties.getEngine(), this.loginProperties.getDatabase());
-		return loginProperties.toBuilder().host(engine.getEndpoint()).engine(engine.getName()).build();*/
-		//temporary workaround
-		return internalSystemEngineProperties.toBuilder().build();
+	private FireboltProperties getSessionPropertiesForNonSystemEngine() throws FireboltException {
+		Engine engine = fireboltEngineService.getEngine(loginProperties.getEngine(), loginProperties.getDatabase());
+		return loginProperties.toBuilder().host(engine.getEndpoint()).engine(engine.getName()).systemEngine(false).build();
 	}
 
 	private FireboltProperties createInternalSystemEngineProperties(String accessToken, String account) throws FireboltException {
@@ -143,7 +144,7 @@ private FireboltProperties createInternalSystemEngineProperties(String accessTok
 				.systemEngine(true)
 				.engine(SYSTEM_ENGINE_NAME)
 				.compress(false)
-				.host(URI.create(systemEngineEndpoint).getHost()).database(null).build();
+				.host(UrlUtil.createUrl(systemEngineEndpoint).getHost()).database(null).build();
 	}
 
 	public void removeExpiredTokens() throws FireboltException {
@@ -179,10 +180,6 @@ public Statement createStatement(FireboltProperties fireboltProperties) throws S
 		return fireboltStatement;
 	}
 
-	public Statement createSystemEngineStatementStatement() throws SQLException {
-		return createStatement(internalSystemEngineProperties);
-	}
-
 	private void addStatement(FireboltStatement statement) throws SQLException {
 		synchronized (statements) {
 			this.validateConnectionIsNotClose();
diff --git a/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java b/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
index e666dc77d..bc32fa51e 100644
--- a/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
+++ b/src/main/java/com/firebolt/jdbc/connection/UrlUtil.java
@@ -5,7 +5,9 @@
 import lombok.experimental.UtilityClass;
 import org.apache.commons.lang3.StringUtils;
 
+import java.net.MalformedURLException;
 import java.net.URI;
+import java.net.URL;
 import java.util.Optional;
 import java.util.Properties;
 
@@ -41,4 +43,19 @@ private static Properties parseUriQueryPart(String jdbcConnectionString) {
                 .ifPresent(port -> uriProperties.put(FireboltSessionProperty.PORT.getKey(), String.valueOf(port)));
         return uriProperties;
     }
+
+    /**
+     * This factory method is similar to {@link URI#create(String)}.
+     * The difference is that `URI.host` of {@code http://something} is {@code null} while
+     * URL spec {@code http://something/} returns URI with host=something.
+     * @param spec – the String to parse as a URL.
+     * @return URL instance
+     */
+    public static URL createUrl(String spec) {
+        try {
+            return new URL(spec);
+        } catch (MalformedURLException e) {
+            throw new IllegalArgumentException(e.getMessage(), e);
+        }
+    }
 }
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index 7966e2a8a..8f523a117 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -1,17 +1,16 @@
 package com.firebolt.jdbc.connection.settings;
 
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
-
 import lombok.Builder;
 import lombok.CustomLog;
 import lombok.NonNull;
 import lombok.Value;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 @Value
 @Builder(toBuilder = true)
@@ -46,10 +45,11 @@ public class FireboltProperties {
 	String sslCertificatePath;
 	String sslMode;
 	boolean compress;
-	String user;
-	String password;
+	String principal;
+	String secret;
 	String engine;
 	String account;
+	String accountId;
 	Integer tcpKeepIdle;
 	Integer tcpKeepCount;
 	Integer tcpKeepInterval;
@@ -68,8 +68,8 @@ public static FireboltProperties of(Properties... properties) {
 		boolean ssl = getSetting(mergedProperties, FireboltSessionProperty.SSL);
 		String sslRootCertificate = getSetting(mergedProperties, FireboltSessionProperty.SSL_CERTIFICATE_PATH);
 		String sslMode = getSetting(mergedProperties, FireboltSessionProperty.SSL_MODE);
-		String user = getSetting(mergedProperties, FireboltSessionProperty.USER);
-		String password = getSetting(mergedProperties, FireboltSessionProperty.PASSWORD);
+		String principal = getSetting(mergedProperties, FireboltSessionProperty.CLIENT_ID);
+		String secret = getSetting(mergedProperties, FireboltSessionProperty.CLIENT_SECRET);
 		String path = getSetting(mergedProperties, FireboltSessionProperty.PATH);
 		String database = getDatabase(mergedProperties, path);
 		String engine = getEngine(mergedProperties, database);
@@ -97,7 +97,7 @@ public static FireboltProperties of(Properties... properties) {
 		Map<String, String> additionalProperties = getFireboltCustomProperties(mergedProperties);
 
 		return FireboltProperties.builder().ssl(ssl).sslCertificatePath(sslRootCertificate).sslMode(sslMode).path(path)
-				.port(port).database(database).compress(compress).user(user).password(password).host(host)
+				.port(port).database(database).compress(compress).principal(principal).secret(secret).host(host)
 				.additionalProperties(additionalProperties).account(account).engine(engine)
 				.keepAliveTimeoutMillis(keepAliveMillis).maxConnectionsTotal(maxTotal).maxRetries(maxRetries)
 				.bufferSize(bufferSize).socketTimeoutMillis(socketTimeout).connectionTimeoutMillis(connectionTimeout)
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltQueryParameterKey.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltQueryParameterKey.java
index ee2a183a3..41d503f98 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltQueryParameterKey.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltQueryParameterKey.java
@@ -6,8 +6,13 @@
 @RequiredArgsConstructor
 @Getter
 public enum FireboltQueryParameterKey {
-	DATABASE("database"), QUERY_ID("query_id"), COMPRESS("compress"), DEFAULT_FORMAT("default_format"),
-	OUTPUT_FORMAT("output_format");
+	DATABASE("database"),
+	QUERY_ID("query_id"),
+	COMPRESS("compress"),
+	DEFAULT_FORMAT("default_format"),
+	OUTPUT_FORMAT("output_format"),
+	ACCOUNT_ID("account_id"),
+	;
 
 	private final String key;
 }
\ No newline at end of file
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
index 5373bb9d0..3690f90f4 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
@@ -44,12 +44,13 @@ public enum FireboltSessionProperty {
 				 */
 			"compress", true, Boolean.class, "Whether to compress transferred data or not. Compressed by default"),
 	DATABASE("database", null, String.class, "default database name"),
-	PASSWORD("password", null, String.class, "user password - null by default"),
-	USER("user", null, String.class, "user name - null by default"),
+	CLIENT_SECRET("client_secret", null, String.class, "user password - null by default", "password"),
+	CLIENT_ID("client_id", null, String.class, "user name - null by default", "user"),
 	HOST("host", null, String.class, "Firebolt host - null by default"),
 	PORT("port", null, Integer.class, "Firebolt port - null by default"),
 	ENGINE("engine", null, String.class, "engine - null by default", "engine_name"),
 	ACCOUNT("account", "firebolt", String.class, "account - null by default"),
+	ACCOUNT_ID("account_id", "firebolt", String.class, "accountId - null by default"),
 	LOG_RESULT_SET("log_result_set", false, Boolean.class,
 			"When set to true, the result of the queries executed are logged with the log level INFO. This has a negative performance impact and should be enabled only for debugging purposes"),
 	USER_DRIVERS("user_drivers", null, String.class, "user drivers"),
diff --git a/src/main/java/com/firebolt/jdbc/metadata/FireboltDatabaseMetadata.java b/src/main/java/com/firebolt/jdbc/metadata/FireboltDatabaseMetadata.java
index 0e4b4c802..63d749479 100644
--- a/src/main/java/com/firebolt/jdbc/metadata/FireboltDatabaseMetadata.java
+++ b/src/main/java/com/firebolt/jdbc/metadata/FireboltDatabaseMetadata.java
@@ -352,7 +352,7 @@ public boolean allTablesAreSelectable() throws SQLException {
 	@Override
 	@ExcludeFromJacocoGeneratedReport
 	public String getUserName() throws SQLException {
-		return connection.getSessionProperties().getUser();
+		return connection.getSessionProperties().getPrincipal();
 	}
 
 	@Override
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltAccountIdService.java b/src/main/java/com/firebolt/jdbc/service/FireboltAccountIdService.java
new file mode 100644
index 000000000..f49c3d282
--- /dev/null
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltAccountIdService.java
@@ -0,0 +1,17 @@
+package com.firebolt.jdbc.service;
+
+import com.firebolt.jdbc.client.account.FireboltAccount;
+import com.firebolt.jdbc.client.account.FireboltAccountRetriever;
+import com.firebolt.jdbc.exception.FireboltException;
+
+public class FireboltAccountIdService {
+    private final FireboltAccountRetriever<FireboltAccount> firebolAccountClient;
+
+    public FireboltAccountIdService(FireboltAccountRetriever<FireboltAccount> firebolAccountClient) {
+        this.firebolAccountClient = firebolAccountClient;
+    }
+
+    public String getValue(String accessToken, String account) throws FireboltException {
+        return firebolAccountClient.retrieve(accessToken, account).getId();
+    }
+}
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java b/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
index 1762fba39..af697198e 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltAuthenticationService.java
@@ -1,23 +1,22 @@
 package com.firebolt.jdbc.service;
 
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.lang3.StringUtils;
-
 import com.firebolt.jdbc.client.authentication.FireboltAuthenticationClient;
 import com.firebolt.jdbc.connection.FireboltConnectionTokens;
 import com.firebolt.jdbc.connection.settings.FireboltProperties;
 import com.firebolt.jdbc.exception.FireboltException;
-
 import lombok.CustomLog;
 import lombok.EqualsAndHashCode;
 import lombok.RequiredArgsConstructor;
-import net.jodah.expiringmap.ExpirationPolicy;
 import net.jodah.expiringmap.ExpiringMap;
+import org.apache.commons.codec.binary.Hex;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Optional;
+
+import static java.lang.String.format;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static net.jodah.expiringmap.ExpirationPolicy.CREATED;
 
 @RequiredArgsConstructor
 @CustomLog
@@ -32,36 +31,29 @@ public class FireboltAuthenticationService {
 	public FireboltConnectionTokens getConnectionTokens(String host, FireboltProperties loginProperties)
 			throws FireboltException {
 		try {
-			ConnectParams connectionParams = new ConnectParams(host, loginProperties.getUser(),
-					loginProperties.getPassword());
+			ConnectParams connectionParams = new ConnectParams(host, loginProperties.getPrincipal(), loginProperties.getSecret());
 			synchronized (this) {
 				FireboltConnectionTokens foundToken = tokensMap.get(connectionParams);
 				if (foundToken != null) {
 					log.debug("Using the token of {} from the cache", host);
 					return foundToken;
-				} else {
-					FireboltConnectionTokens fireboltConnectionTokens = fireboltAuthenticationClient
-							.postConnectionTokens(host, loginProperties.getUser(), loginProperties.getPassword(), loginProperties.getEnvironment());
-					long durationInSeconds = getCachingDurationInSeconds(
-							fireboltConnectionTokens.getExpiresInSeconds());
-					tokensMap.put(connectionParams, fireboltConnectionTokens, ExpirationPolicy.CREATED,
-							durationInSeconds, TimeUnit.SECONDS);
-					return fireboltConnectionTokens;
 				}
+				FireboltConnectionTokens fireboltConnectionTokens = fireboltAuthenticationClient
+						.postConnectionTokens(host, loginProperties.getPrincipal(), loginProperties.getSecret(), loginProperties.getEnvironment());
+				long durationInSeconds = getCachingDurationInSeconds(fireboltConnectionTokens.getExpiresInSeconds());
+				tokensMap.put(connectionParams, fireboltConnectionTokens, CREATED, durationInSeconds, SECONDS);
+				return fireboltConnectionTokens;
 			}
 		} catch (Exception e) {
 			log.error("Failed to connect to Firebolt", e);
-			if (e instanceof FireboltException
-					&& StringUtils.isNotEmpty(((FireboltException) e).getErrorMessageFromServer())) {
-				throw new FireboltException(String.format(
-						"Failed to connect to Firebolt with the error from the server: %s, see logs for more info.",
-						((FireboltException) e).getErrorMessageFromServer()), e);
-			} else {
-				throw new FireboltException(
-						String.format("Failed to connect to Firebolt with the error: %s, see logs for more info.",
-								e.getMessage()),
-						e);
+			String errorMessageTemplate = "Failed to connect to Firebolt with the error%s: %s, see logs for more info.";
+			if (e instanceof FireboltException) {
+				String server = ((FireboltException) e).getErrorMessageFromServer();
+				if (server != null) {
+					throw new FireboltException(format(errorMessageTemplate, " from the server", server), e);
+				}
 			}
+			throw new FireboltException(format(errorMessageTemplate, "", e.getMessage()), e);
 		}
 	}
 
@@ -83,8 +75,7 @@ private long getCachingDurationInSeconds(long expireInSeconds) {
 	public void removeConnectionTokens(String host, FireboltProperties loginProperties) throws FireboltException {
 		try {
 			log.debug("Removing connection token for host {}", host);
-			ConnectParams connectionParams = new ConnectParams(host, loginProperties.getUser(),
-					loginProperties.getPassword());
+			ConnectParams connectionParams = new ConnectParams(host, loginProperties.getPrincipal(), loginProperties.getSecret());
 			tokensMap.remove(connectionParams);
 		} catch (NoSuchAlgorithmException e) {
 			throw new FireboltException("Could not remove connection tokens", e);
@@ -96,11 +87,11 @@ private static class ConnectParams {
 		public final String fireboltHost;
 		public final String credentialsHash;
 
-		public ConnectParams(String fireboltHost, String user, String password) throws NoSuchAlgorithmException {
+		public ConnectParams(String fireboltHost, String principal, String secret) throws NoSuchAlgorithmException {
 			this.fireboltHost = fireboltHost;
 			MessageDigest sha256Instance = MessageDigest.getInstance("SHA-256");
-			Optional.ofNullable(user).map(String::getBytes).ifPresent(sha256Instance::update);
-			Optional.ofNullable(password).map(String::getBytes).ifPresent(sha256Instance::update);
+			Optional.ofNullable(principal).map(String::getBytes).ifPresent(sha256Instance::update);
+			Optional.ofNullable(secret).map(String::getBytes).ifPresent(sha256Instance::update);
 			this.credentialsHash = new String(Hex.encodeHex(sha256Instance.digest()));
 		}
 	}
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
index c7f59f3df..ed562548d 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
@@ -1,28 +1,28 @@
 package com.firebolt.jdbc.service;
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Optional;
-
-import javax.annotation.Nullable;
-
-import org.apache.commons.lang3.StringUtils;
-
+import com.firebolt.jdbc.CheckedFunction;
 import com.firebolt.jdbc.connection.Engine;
 import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
-
 import lombok.CustomLog;
 import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.annotation.Nullable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Optional;
+
+import static java.lang.String.format;
 
 @RequiredArgsConstructor
 @CustomLog
 public class FireboltEngineService {
-    private static final String ENGINE_URL = "engine_url";
+    private static final String ENGINE_URL = "url";
     private static final String ENGINE_NAME = "engine_name";
     private static final String STATUS_FIELD_NAME = "status";
-    private static final String DEFAULT_ENGINE_QUERY = "SELECT engs.engine_url, engs.status, engs.engine_name\n" +
+    private static final String DEFAULT_ENGINE_QUERY = "SELECT engs.url, engs.status, engs.engine_name\n" +
             "FROM information_schema.databases AS dbs\n" +
             "INNER JOIN information_schema.engines AS engs\n" +
             "ON engs.attached_to = dbs.database_name\n" +
@@ -30,9 +30,8 @@ public class FireboltEngineService {
             "        eng_name -> eng_name LIKE '%%(default)',\n" +
             "        SPLIT(',', attached_engines)\n" +
             "    ), ' ', 1), '')\n" +
-            "WHERE database_name = '%s'";
-    private static final String ENGINE_QUERY = "SELECT engine_url, attached_to, status FROM information_schema.engines \n" +
-            "WHERE engine_name='%s'";
+            "WHERE database_name = ?";
+    private static final String ENGINE_QUERY = "SELECT url, status FROM information_schema.engines WHERE engine_name=?";
     private static final String RUNNING_STATUS = "running";
     private final FireboltConnection fireboltConnection;
 
@@ -45,7 +44,7 @@ public class FireboltEngineService {
     public String getEngineNameByHost(String engineHost) throws FireboltException {
         return Optional.ofNullable(engineHost).filter(host -> host.contains(".")).map(host -> host.split("\\.")[0])
                 .map(host -> host.replace("-", "_")).orElseThrow(() -> new FireboltException(
-                        String.format("Could not establish the engine from the host: %s", engineHost)));
+                        format("Could not establish the engine from the host: %s", engineHost)));
     }
 
     public Engine getEngine(@Nullable String name, @Nullable String database) throws FireboltException {
@@ -57,40 +56,38 @@ public Engine getEngine(@Nullable String name, @Nullable String database) throws
     }
 
     private Engine getDefaultEngine(String database) throws FireboltException {
-        try (Statement statement = this.fireboltConnection.createSystemEngineStatementStatement();
-             ResultSet resultSet = statement.executeQuery(String.format(DEFAULT_ENGINE_QUERY, database))) {
-            if (!resultSet.next()) {
-                throw new FireboltException(String.format("The default engine for the database %s could not be found", database));
-            }
-            String status = resultSet.getString(STATUS_FIELD_NAME);
-            if (isEngineNotRunning(status)) {
-                throw new FireboltException(String.format("The default engine for the database %s is not running. Status: %s", database, status));
-            }
-            return Engine.builder().endpoint(resultSet.getString(ENGINE_URL)).name(resultSet.getString(ENGINE_NAME)).build();
-        } catch (SQLException sqlException) {
-            throw new FireboltException(String.format("Could not get default engine url for database %s", database), sqlException);
-        }
+        return getRowValue(DEFAULT_ENGINE_QUERY, database, rs -> Engine.builder().endpoint(rs.getString(ENGINE_URL)).name(rs.getString(ENGINE_NAME)).build(),
+                "The default engine for the database %s could not be found",
+                "The default engine for the database %s is not running. Status: %s",
+                "Could not get default engine url for database %s");
     }
 
     private String getEngineEndpoint(String engine) throws FireboltException {
-        try (Statement statement = this.fireboltConnection.createSystemEngineStatementStatement();
-             ResultSet resultSet = statement.executeQuery(String.format(ENGINE_QUERY, engine))) {
-            if (!resultSet.next()) {
-                throw new FireboltException(String.format("The engine with the name %s could not be found", engine));
-            }
-            String status = resultSet.getString(STATUS_FIELD_NAME);
-            if (isEngineNotRunning(status)) {
-                throw new FireboltException(String.format("The engine with the name %s is not running. Status: %s", engine, status));
+        return getRowValue(ENGINE_QUERY, engine, rs -> rs.getString(ENGINE_URL),
+                "The engine with the name %s could not be found",
+                "The engine with the name %s is not running. Status: %s",
+                "Could not get engine url for engine %s");
+    }
+
+    private <T> T getRowValue(String query, String queryArg, CheckedFunction<ResultSet, T> valueExtractor, String noDataMessage, String engineNotRunningMessage, String sqlFailureMessage) throws FireboltException {
+        try (PreparedStatement ps = fireboltConnection.prepareStatement(query)) {
+            ps.setString(1, queryArg);
+            try (ResultSet rs = ps.executeQuery()) {
+                if (!rs.next()) {
+                    throw new FireboltException(format(noDataMessage, queryArg));
+                }
+                String status = rs.getString(STATUS_FIELD_NAME);
+                if (isEngineNotRunning(status)) {
+                    throw new FireboltException(format(engineNotRunningMessage, queryArg, status));
+                }
+                return valueExtractor.apply(rs);
             }
-            return resultSet.getString(ENGINE_URL);
-        } catch (SQLException sqlException) {
-            throw new FireboltException(String.format("Could not get engine url for engine %s", engine), sqlException);
+        } catch (SQLException e) {
+            throw new FireboltException(format(sqlFailureMessage, queryArg), e);
         }
     }
 
     private boolean isEngineNotRunning(String status) {
-        return !StringUtils.equalsIgnoreCase(RUNNING_STATUS, status);
+        return !RUNNING_STATUS.equalsIgnoreCase(status);
     }
-
-
 }
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java b/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
index 0b91d0b87..f3df43fe4 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltGatewayUrlService.java
@@ -1,15 +1,16 @@
 package com.firebolt.jdbc.service;
 
-import com.firebolt.jdbc.client.gateway.FireboltGatewayUrlClient;
+import com.firebolt.jdbc.client.account.FireboltAccountRetriever;
+import com.firebolt.jdbc.client.gateway.GatewayUrlResponse;
 import com.firebolt.jdbc.exception.FireboltException;
 import lombok.RequiredArgsConstructor;
 
 @RequiredArgsConstructor
 public class FireboltGatewayUrlService {
 
-    private final FireboltGatewayUrlClient fireboltGatewayUrlClient;
+    private final FireboltAccountRetriever<GatewayUrlResponse> fireboltGatewayUrlClient;
 
     public String getUrl(String accessToken, String account) throws FireboltException {
-        return fireboltGatewayUrlClient.getGatewayUrl(accessToken, account).getEngineUrl();
+        return fireboltGatewayUrlClient.retrieve(accessToken, account).getEngineUrl();
     }
 }
diff --git a/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java b/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java
deleted file mode 100644
index eb0595b81..000000000
--- a/src/test/java/com/firebolt/jdbc/client/account/FireboltAccountClientTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-<<<<<<< HEAD
-package com.firebolt.jdbc.client.account;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.firebolt.jdbc.client.account.response.FireboltAccountResponse;
-import com.firebolt.jdbc.client.account.response.FireboltDefaultDatabaseEngineResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineIdResponse;
-import com.firebolt.jdbc.client.account.response.FireboltEngineResponse;
-import com.firebolt.jdbc.connection.FireboltConnection;
-import com.firebolt.jdbc.exception.FireboltException;
-import com.google.common.collect.ImmutableMap;
-import okhttp3.*;
-import org.junit.function.ThrowingRunnable;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.firebolt.jdbc.client.UserAgentFormatter.userAgent;
-import static java.lang.String.format;
-import static java.net.HttpURLConnection.*;
-import static org.junit.Assert.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-
-@ExtendWith(MockitoExtension.class)
-class FireboltAccountClientTest {
-	private static final String ACCESS_TOKEN = "token";
-	private static final String HOST = "https://host";
-	private static final String ACCOUNT = "account";
-	private static final String ACCOUNT_ID = "account_id";
-	private static final String DB_NAME = "dbName";
-	private static final String ENGINE_NAME = "engineName";
-
-	@Spy
-	private final ObjectMapper objectMapper = new ObjectMapper()
-			.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
-
-	private final ObjectMapper mapper = new ObjectMapper();
-	@Captor
-	private ArgumentCaptor<Request> requestArgumentCaptor;
-	@Mock
-	private OkHttpClient httpClient;
-	@Mock
-	private Call call;
-	private FireboltAccountClient fireboltAccountClient;
-
-	@Mock
-	private FireboltConnection fireboltConnection;
-
-	@BeforeEach
-	void setUp() {
-		fireboltAccountClient = new FireboltAccountClient(httpClient, objectMapper, fireboltConnection, "ConnA:1.0.9",
-				"ConnB:2.0.9");
-		when(httpClient.newCall(any())).thenReturn(call);
-	}
-
-	@Test
-	void shouldGetAccountId() throws Exception {
-		Response response = mock(Response.class);
-		when(response.code()).thenReturn(HTTP_OK);
-		ResponseBody body = mock(ResponseBody.class);
-		when(body.string()).thenReturn("{\"account_id\":\"12345\"}");
-		when(response.body()).thenReturn(body);
-		when(call.execute()).thenReturn(response);
-
-		FireboltAccountResponse account = fireboltAccountClient.getAccount(HOST, ACCOUNT, ACCESS_TOKEN);
-
-		Map<String, String> expectedHeader = ImmutableMap.of("User-Agent",
-				userAgent("ConnB/2.0.9 JDBC/%s (Java %s; %s %s; ) ConnA/1.0.9"), "Authorization",
-				"Bearer " + ACCESS_TOKEN);
-
-		verify(httpClient).newCall(requestArgumentCaptor.capture());
-		verify(objectMapper).readValue("{\"account_id\":\"12345\"}", FireboltAccountResponse.class);
-		assertEquals("https://host/iam/v2/accounts:getIdByName?accountName=" + ACCOUNT,
-				requestArgumentCaptor.getValue().url().toString());
-		assertEquals(expectedHeader, extractHeadersMap(requestArgumentCaptor.getValue()));
-		assertEquals("12345", account.getAccountId());
-	}
-
-	@Test
-	void shouldGetEngineEndpoint() throws Exception {
-		Response response = mock(Response.class);
-		when(response.code()).thenReturn(HTTP_OK);
-		ResponseBody body = mock(ResponseBody.class);
-		when(response.body()).thenReturn(body);
-		when(call.execute()).thenReturn(response);
-		when(response.body().string()).thenReturn(mapper.writeValueAsString(FireboltEngineResponse.builder()
-				.engine(FireboltEngineResponse.Engine.builder().endpoint("http://engineEndpoint").build()).build()));
-		when(httpClient.newCall(any())).thenReturn(call);
-
-		FireboltEngineResponse engine = fireboltAccountClient.getEngine(HOST, ENGINE_NAME, DB_NAME, ACCOUNT_ID,
-				ACCESS_TOKEN);
-		Map<String, String> expectedHeader = ImmutableMap.of("User-Agent",
-				userAgent("ConnB/2.0.9 JDBC/%s (Java %s; %s %s; ) ConnA/1.0.9"), "Authorization",
-				"Bearer " + ACCESS_TOKEN);
-
-		verify(httpClient).newCall(requestArgumentCaptor.capture());
-		verify(objectMapper).readValue("{\"engine\":{\"endpoint\":\"http://engineEndpoint\",\"current_status\":null}}",
-				FireboltEngineResponse.class);
-		verify(httpClient).newCall(requestArgumentCaptor.capture());
-		assertEquals("https://host/core/v1/accounts/engineName/engines/" + ACCOUNT_ID,
-				requestArgumentCaptor.getValue().url().toString());
-		assertEquals(expectedHeader, extractHeadersMap(requestArgumentCaptor.getValue()));
-		assertEquals("http://engineEndpoint", engine.getEngine().getEndpoint());
-	}
-
-	@Test
-	void shouldGetDbAddress() throws Exception {
-		Response response = mock(Response.class);
-		when(response.code()).thenReturn(HTTP_OK);
-		ResponseBody body = mock(ResponseBody.class);
-		when(response.body()).thenReturn(body);
-		when(call.execute()).thenReturn(response);
-		when(response.body().string()).thenReturn(mapper
-				.writeValueAsString(FireboltDefaultDatabaseEngineResponse.builder().engineUrl("http://dbAddress").build()));
-
-		FireboltDefaultDatabaseEngineResponse fireboltDefaultDatabaseEngineResponse = fireboltAccountClient
-				.getDefaultEngineByDatabaseName(HOST, ACCOUNT_ID, DB_NAME, ACCESS_TOKEN);
-		Map<String, String> expectedHeader = ImmutableMap.of("User-Agent",
-				userAgent("ConnB/2.0.9 JDBC/%s (Java %s; %s %s; ) ConnA/1.0.9"), "Authorization",
-				"Bearer " + ACCESS_TOKEN);
-
-		verify(httpClient).newCall(requestArgumentCaptor.capture());
-		verify(objectMapper).readValue("{\"engine_url\":\"http://dbAddress\"}", FireboltDefaultDatabaseEngineResponse.class);
-		assertEquals(format("https://host/core/v1/accounts/%s/engines:getURLByDatabaseName?databaseName=%s",
-				ACCOUNT_ID, DB_NAME), requestArgumentCaptor.getValue().url().toString());
-		assertEquals(expectedHeader, extractHeadersMap(requestArgumentCaptor.getValue()));
-		assertEquals("http://dbAddress", fireboltDefaultDatabaseEngineResponse.getEngineUrl());
-	}
-
-	@Test
-	void shouldGetEngineId() throws Exception {
-		Response response = mock(Response.class);
-		when(response.code()).thenReturn(HTTP_OK);
-		ResponseBody body = mock(ResponseBody.class);
-		when(response.body()).thenReturn(body);
-		when(call.execute()).thenReturn(response);
-		when(response.body().string()).thenReturn(mapper.writeValueAsString(FireboltEngineIdResponse.builder()
-				.engine(FireboltEngineIdResponse.Engine.builder().engineId("13").build()).build()));
-
-		FireboltEngineIdResponse fireboltEngineIdResponse = fireboltAccountClient.getEngineId(HOST, ACCOUNT_ID,
-				ENGINE_NAME, ACCESS_TOKEN);
-		Map<String, String> expectedHeader = ImmutableMap.of("User-Agent",
-				userAgent("ConnB/2.0.9 JDBC/%s (Java %s; %s %s; ) ConnA/1.0.9"), "Authorization",
-				"Bearer " + ACCESS_TOKEN);
-
-		verify(httpClient).newCall(requestArgumentCaptor.capture());
-		verify(objectMapper).readValue("{\"engine_id\":{\"engine_id\":\"13\"}}", FireboltEngineIdResponse.class);
-		assertEquals(format("https://host/core/v1/accounts/%s/engines:getIdByName?engine_name=%s", ACCOUNT_ID,
-				ENGINE_NAME), requestArgumentCaptor.getValue().url().toString());
-		assertEquals(expectedHeader, extractHeadersMap(requestArgumentCaptor.getValue()));
-		assertEquals("13", fireboltEngineIdResponse.getEngine().getEngineId());
-	}
-
-	@Test
-	void shouldThrowExceptionWhenStatusCodeIsNotFound() throws Exception {
-		shouldThrowException(HTTP_NOT_FOUND, () -> fireboltAccountClient.getAccount(HOST, ACCOUNT, ACCESS_TOKEN), null);
-	}
-
-	@Test
-	void shouldThrowExceptionWhenStatusCodeIsNotOk() throws Exception {
-		shouldThrowException(HTTP_BAD_GATEWAY, () -> fireboltAccountClient.getAccount(HOST, ACCOUNT, ACCESS_TOKEN), null);
-	}
-
-	@Test
-	void shouldThrowExceptionWithDBNotFoundErrorMessageWhenDBIsNotFound() throws Exception {
-		shouldThrowException(HTTP_NOT_FOUND, () -> fireboltAccountClient.getDefaultEngineByDatabaseName(HOST, ACCOUNT, DB_NAME, ACCESS_TOKEN), "The database with the name dbName could not be found");
-	}
-
-	@Test
-	void shouldThrowExceptionWithEngineNotFoundErrorMessageWhenEngineAddressIsNotFound() throws Exception {
-		shouldThrowException(HTTP_NOT_FOUND, () -> fireboltAccountClient.getEngine(HOST, ACCOUNT, ENGINE_NAME, "123", ACCESS_TOKEN), "The address of the engine with name engineName and id 123 could not be found");
-	}
-
-	@Test
-	void shouldThrowExceptionWithEngineNotFoundErrorMessageWhenEngineIdIsNotFound() throws Exception {
-		shouldThrowException(HTTP_NOT_FOUND, () -> fireboltAccountClient.getEngineId(HOST, ACCOUNT, ENGINE_NAME, ACCESS_TOKEN), "The engine engineName could not be found");
-	}
-
-	private void shouldThrowException(int httpStatus, ThrowingRunnable runnable, String expectedMessage) throws Exception {
-		Response response = mock(Response.class);
-		when(response.code()).thenReturn(httpStatus);
-		ResponseBody body = mock(ResponseBody.class);
-		when(response.body()).thenReturn(body);
-		when(call.execute()).thenReturn(response);
-		FireboltException fireboltException = assertThrows(FireboltException.class, runnable);
-		if (expectedMessage != null) {
-			assertEquals(expectedMessage, fireboltException.getMessage());
-		}
-	}
-
-	private Map<String, String> extractHeadersMap(Request request) {
-		Map<String, String> headers = new HashMap<>();
-		request.headers().forEach(header -> headers.put(header.getFirst(), header.getSecond()));
-		return headers;
-	}
-}
-=======
->>>>>>> 5242315 (Start adding support for new identity)
diff --git a/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java b/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
index e2c887f5d..5d705858e 100644
--- a/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/authentication/ServiceAccountAuthenticationRequestTest.java
@@ -1,8 +1,11 @@
 package com.firebolt.jdbc.client.authentication;
 
+import static java.lang.String.format;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.IOException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
 
 import org.junit.jupiter.api.Test;
 
@@ -19,7 +22,7 @@ void shouldCreateHttpEntityWithTheProvidedCredentials() throws IOException {
 		Buffer buffer = new Buffer();
 		requestBody.writeTo(buffer);
 
-		assertEquals("audience=https%3A%2F%2Fdev-firebolt-v2.us.auth0.com%2Fapi%2Fv2%2F&grant_type=client_credentials&client_id=he-ll-o&client_secret=secret", buffer.readUtf8());
+		assertEquals(format("audience=%s&grant_type=client_credentials&client_id=he-ll-o&client_secret=secret", URLEncoder.encode("https://api.firebolt.io", StandardCharsets.UTF_8)), buffer.readUtf8());
 	}
 
 }
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
index 27b666790..4fcb1639c 100644
--- a/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
@@ -1,35 +1,32 @@
 package com.firebolt.jdbc.client.gateway;
 
-import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
-import static java.net.HttpURLConnection.HTTP_OK;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-
-import com.firebolt.jdbc.exception.ExceptionType;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.firebolt.jdbc.client.account.FireboltAccount;
+import com.firebolt.jdbc.client.account.FireboltAccountRetriever;
 import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
-
 import okhttp3.Call;
 import okhttp3.OkHttpClient;
 import okhttp3.Response;
 import okhttp3.ResponseBody;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.io.IOException;
+
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
-class FireboltGatewayUrlClientTest {
+class FireboltAccountRetrieverTest {
 
 	@Spy
 	private final ObjectMapper objectMapper = new ObjectMapper();
@@ -40,24 +37,45 @@ class FireboltGatewayUrlClientTest {
 	@Mock
 	private FireboltConnection fireboltConnection;
 
-    @InjectMocks
-    private FireboltGatewayUrlClient fireboltGatewayUrlClient;
+    private FireboltAccountRetriever<GatewayUrlResponse> fireboltGatewayUrlClient;
+    private FireboltAccountRetriever<FireboltAccount> fireboltAccountIdResolver;
+
+
+    @BeforeEach
+    void setUp() {
+        fireboltGatewayUrlClient = new FireboltAccountRetriever<>(httpClient, fireboltConnection, null, null, objectMapper, "engineUrl", GatewayUrlResponse.class);
+        fireboltAccountIdResolver = new FireboltAccountRetriever<>(httpClient, fireboltConnection, null, null, objectMapper, "resolve", FireboltAccount.class);
+    }
 
 	@Test
 	void shouldGetGatewayUrlWhenResponseIsOk() throws IOException, FireboltException {
         GatewayUrlResponse response = GatewayUrlResponse.builder().engineUrl("http://engine").build();
         injectMockedResponse(httpClient, HTTP_OK, response);
-        assertEquals("http://engine", fireboltGatewayUrlClient.getGatewayUrl("access_token", "account").getEngineUrl());
+        assertEquals("http://engine", fireboltGatewayUrlClient.retrieve("access_token", "account").getEngineUrl());
 	}
 
     @Test
-    void shouldThrowFireboltExceptionUponException() {
+    void shouldGetAccountId() throws IOException, FireboltException {
+        FireboltAccount account = new FireboltAccount("12345", "central");
+        injectMockedResponse(httpClient, HTTP_OK, account);
+        assertEquals(account, fireboltAccountIdResolver.retrieve("access_token", "account"));
+    }
+
+    @Test
+    void shouldRuntimeExceptionUponRuntimeException() throws FireboltException {
         when(httpClient.newCall(any())).thenThrow(new IllegalArgumentException("ex"));
-        Exception ex = assertThrows(FireboltException.class, () ->fireboltGatewayUrlClient.getGatewayUrl("token", "acc"));
-        assertEquals("Failed to get gateway url for account acc", ex.getMessage());
+        assertEquals("ex", assertThrows(IllegalArgumentException.class, () -> fireboltGatewayUrlClient.retrieve("token", "acc")).getMessage());
+    }
+
+    @Test
+    void shouldThrowFireboltExceptionUponIOException() throws IOException {
+        Call call = mock(Call.class);
+        when(httpClient.newCall(any())).thenReturn(call);
+        when(call.execute()).thenThrow(new IOException("ex"));
+        assertEquals("Failed to get engineUrl url for account acc", assertThrows(FireboltException.class, () -> fireboltGatewayUrlClient.retrieve("token", "acc")).getMessage());
     }
 
-    private void injectMockedResponse(OkHttpClient httpClient, int code, GatewayUrlResponse gatewayUrlResponse) throws IOException {
+    private void injectMockedResponse(OkHttpClient httpClient, int code, Object payload) throws IOException {
         Response response = mock(Response.class);
         Call call = mock(Call.class);
         when(httpClient.newCall(any())).thenReturn(call);
@@ -65,8 +83,7 @@ private void injectMockedResponse(OkHttpClient httpClient, int code, GatewayUrlR
         ResponseBody body = mock(ResponseBody.class);
         when(response.body()).thenReturn(body);
         when(response.code()).thenReturn(code);
-        String gatewayResponse = new ObjectMapper()
-                .writeValueAsString(gatewayUrlResponse);
+        String gatewayResponse = new ObjectMapper().writeValueAsString(payload);
         when(body.string()).thenReturn(gatewayResponse);
     }
 }
\ No newline at end of file
diff --git a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
index bf4a7c0ad..425080211 100644
--- a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
@@ -74,7 +74,7 @@ void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 	@Test
 	void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException, URISyntaxException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db1").compress(true)
-				.host("firebolt1").port(555).build();
+				.host("firebolt1").port(555).accountId("12345").build();
 		when(connection.getAccessToken())
 				.thenReturn(Optional.of("token"));
 		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
@@ -90,7 +90,7 @@ void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException,
 		String actualQuery = getActualRequestString(actualRequest);
 
 		assertEquals("show databases;", actualQuery);
-		assertEquals("http://firebolt1:555/dynamic/query?output_format=TabSeparatedWithNamesAndTypes",
+		assertEquals("http://firebolt1:555/?account_id=12345&output_format=TabSeparatedWithNamesAndTypes",
 				actualRequest.url().toString());
 	}
 
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index aa65e43a5..509ef5f26 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -1,35 +1,30 @@
 package com.firebolt.jdbc.connection;
 
-import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-import java.sql.*;
-import java.util.Optional;
-import java.util.Properties;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import com.firebolt.jdbc.service.FireboltEngineService;
-import com.firebolt.jdbc.service.FireboltGatewayUrlService;
+import com.firebolt.jdbc.connection.settings.FireboltProperties;
+import com.firebolt.jdbc.exception.ExceptionType;
+import com.firebolt.jdbc.exception.FireboltException;
+import com.firebolt.jdbc.service.*;
+import com.firebolt.jdbc.statement.StatementInfoWrapper;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.*;
 import org.mockito.junit.jupiter.MockitoExtension;
 
-import com.firebolt.jdbc.connection.settings.FireboltProperties;
-import com.firebolt.jdbc.exception.ExceptionType;
-import com.firebolt.jdbc.exception.FireboltException;
-import com.firebolt.jdbc.service.FireboltAuthenticationService;
-import com.firebolt.jdbc.service.FireboltStatementService;
-import com.firebolt.jdbc.statement.StatementInfoWrapper;
+import java.sql.*;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
 
 @ExtendWith(MockitoExtension.class)
 class FireboltConnectionTest {
@@ -53,154 +48,157 @@ class FireboltConnectionTest {
 	private FireboltEngineService fireboltEngineService;
 	@Mock
 	private FireboltStatementService fireboltStatementService;
+	@Mock
+	private FireboltAccountIdService fireboltAccountIdService;
 	private Properties connectionProperties = new Properties();
+	private Engine engine;
+
 
 	@BeforeEach
 	void init() throws FireboltException {
 		connectionProperties = new Properties();
-		connectionProperties.put("user", "user");
-		connectionProperties.put("password", "pa$$word");
+		connectionProperties.put("client_id", "somebody");
+		connectionProperties.put("client_secret", "pa$$word");
 		connectionProperties.put("compress", "1");
 		lenient().when(fireboltAuthenticationService.getConnectionTokens(eq("https://api.dev.firebolt.io:443"), any()))
 				.thenReturn(fireboltConnectionTokens);
-		lenient().when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("url");
+		lenient().when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://foo:8080/bar");
+		engine = new Engine("endpoint", "id123", "OK", "noname");
+		lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(engine);
 	}
 
 	@Test
 	void shouldInitConnection() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertFalse(fireboltConnection.isClosed());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertFalse(fireboltConnection.isClosed());
+		}
 	}
 
 	@Test
 	void shouldNotFetchTokenNorEngineHostForLocalFirebolt() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(LOCAL_URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		verifyNoInteractions(fireboltAuthenticationService);
-		verifyNoInteractions(fireboltGatewayUrlService);
-		assertFalse(fireboltConnection.isClosed());
+		try (FireboltConnection fireboltConnection = createConnection(LOCAL_URL, connectionProperties)) {
+			verifyNoInteractions(fireboltAuthenticationService);
+			verifyNoInteractions(fireboltGatewayUrlService);
+			assertFalse(fireboltConnection.isClosed());
+		}
 	}
 
 	@Test
 	void shouldPrepareStatement() throws SQLException {
 		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
 				.thenReturn(Optional.empty());
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		PreparedStatement statement = fireboltConnection
-				.prepareStatement("INSERT INTO cars(sales, name) VALUES (?, ?)");
-		statement.setObject(1, 500);
-		statement.setObject(2, "Ford");
-		statement.execute();
-		assertNotNull(fireboltConnection);
-		assertNotNull(statement);
-		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any());
-		assertEquals("INSERT INTO cars(sales, name) VALUES (500, 'Ford')",
-				queryInfoWrapperArgumentCaptor.getValue().getSql());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			PreparedStatement statement = fireboltConnection
+					.prepareStatement("INSERT INTO cars(sales, name) VALUES (?, ?)");
+			statement.setObject(1, 500);
+			statement.setObject(2, "Ford");
+			statement.execute();
+			assertNotNull(fireboltConnection);
+			assertNotNull(statement);
+			verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
+			assertEquals("INSERT INTO cars(sales, name) VALUES (500, 'Ford')",
+					queryInfoWrapperArgumentCaptor.getValue().getSql());
+		}
 	}
 
 	@Test
 	void shouldCloseAllStatementsOnClose() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		Statement statement = fireboltConnection.createStatement();
-		Statement preparedStatement = fireboltConnection.prepareStatement("test");
-		fireboltConnection.close();
-		assertTrue(statement.isClosed());
-		assertTrue(preparedStatement.isClosed());
-		assertTrue(fireboltConnection.isClosed());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			Statement statement = fireboltConnection.createStatement();
+			Statement preparedStatement = fireboltConnection.prepareStatement("test");
+			fireboltConnection.close();
+			assertTrue(statement.isClosed());
+			assertTrue(preparedStatement.isClosed());
+			assertTrue(fireboltConnection.isClosed());
+		}
 	}
 
 	@Test
 	void shouldNotSetNewPropertyWhenConnectionIsNotValidWithTheNewProperty() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-
-		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
-				.thenThrow(new FireboltException(ExceptionType.TOO_MANY_REQUESTS));
-		assertThrows(FireboltException.class,
-				() -> fireboltConnection.addProperty(new ImmutablePair<>("custom_1", "1")));
-
-		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
-		assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
-		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
-		assertNull(fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
+					.thenThrow(new FireboltException(ExceptionType.TOO_MANY_REQUESTS));
+			assertThrows(FireboltException.class,
+					() -> fireboltConnection.addProperty(new ImmutablePair<>("custom_1", "1")));
+
+			verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
+					propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
+			assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
+			assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
+			assertNull(fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
+		}
 	}
 
 	@Test
 	void shouldSetNewPropertyWhenConnectionIsValidWithTheNewProperty() throws SQLException {
 		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(),anyBoolean(), any()))
 				.thenReturn(Optional.empty());
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
 
-		Pair<String, String> newProperties = new ImmutablePair<>("custom_1", "1");
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			Pair<String, String> newProperties = new ImmutablePair<>("custom_1", "1");
 
-		fireboltConnection.addProperty(newProperties);
+			fireboltConnection.addProperty(newProperties);
 
-		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
-		assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
-		assertEquals("1", fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
-		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
+			verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
+					propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
+			assertEquals("1", propertiesArgumentCaptor.getValue().getAdditionalProperties().get("custom_1"));
+			assertEquals("1", fireboltConnection.getSessionProperties().getAdditionalProperties().get("custom_1"));
+			assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
+		}
 	}
 
 	@Test
 	void shouldValidateConnectionWhenCallingIsValid() throws SQLException {
 		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenReturn(Optional.empty());
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		fireboltConnection.isValid(500);
-
-		verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
-				propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
-		assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			fireboltConnection.isValid(500);
+			verify(fireboltStatementService).execute(queryInfoWrapperArgumentCaptor.capture(),
+					propertiesArgumentCaptor.capture(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any());
+			assertEquals("SELECT 1", queryInfoWrapperArgumentCaptor.getValue().getSql());
+		}
 	}
 
 	@Test
 	void shouldNotValidateConnectionWhenCallingIsValidWhenUsingSystemEngine() throws SQLException {
 		Properties propertiesWithSystemEngine = new Properties(connectionProperties);
-		FireboltConnection fireboltConnection = new FireboltConnection(SYSTEM_ENGINE_URL, propertiesWithSystemEngine,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		fireboltConnection.isValid(500);
-
-		verifyNoInteractions(fireboltStatementService);
+		try (FireboltConnection fireboltConnection = createConnection(SYSTEM_ENGINE_URL, propertiesWithSystemEngine)) {
+			fireboltConnection.isValid(500);
+			verifyNoInteractions(fireboltStatementService);
+		}
 	}
 
 	@Test
 	void shouldIgnore429WhenValidatingConnection() throws SQLException {
 		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenThrow(new FireboltException(ExceptionType.TOO_MANY_REQUESTS));
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertTrue(fireboltConnection.isValid(500));
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertTrue(fireboltConnection.isValid(500));
+		}
 	}
 
 	@Test
 	void shouldReturnFalseWhenValidatingConnectionThrowsAnException() throws SQLException {
 		when(fireboltStatementService.execute(any(), any(), anyInt(), anyInt(), anyBoolean(), anyBoolean(), any()))
 				.thenThrow(new FireboltException(ExceptionType.ERROR));
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertFalse(fireboltConnection.isValid(500));
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertFalse(fireboltConnection.isValid(500));
+		}
 	}
 
 	@Test
 	void shouldThrowExceptionWhenValidatingConnectionWithNegativeTimeout() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertThrows(FireboltException.class, () -> fireboltConnection.isValid(-1));
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertThrows(FireboltException.class, () -> fireboltConnection.isValid(-1));
+		}
 	}
 
 	@Test
 	void shouldReturnFalseWhenValidatingClosedConnection() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		fireboltConnection.close();
-		assertFalse(fireboltConnection.isValid(50));
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			fireboltConnection.close();
+			assertFalse(fireboltConnection.isValid(50));
+		}
 	}
 
 	@Test
@@ -210,69 +208,66 @@ void shouldExtractConnectorOverrides() throws SQLException {
 		connectionProperties.put("user_clients", "ConnA:1.0.9,ConnB:2.8.0");
 		connectionProperties.put("user_drivers", "DriverA:2.0.9,DriverB:3.8.0");
 
-		FireboltConnection fireboltConnectionImpl = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-
-		PreparedStatement statement = fireboltConnectionImpl.prepareStatement("SELECT 1");
-		statement.execute();
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			PreparedStatement statement = fireboltConnection.prepareStatement("SELECT 1");
+			statement.execute();
 
-		verify(fireboltStatementService).execute(any(), propertiesArgumentCaptor.capture(), anyInt(), anyInt(),
-				anyBoolean(), anyBoolean(), any());
-		assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_clients"));
-		assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_drivers"));
-		assertNull(fireboltConnectionImpl.getSessionProperties().getAdditionalProperties().get("user_clients"));
-		assertNull(fireboltConnectionImpl.getSessionProperties().getAdditionalProperties().get("user_drivers"));
+			verify(fireboltStatementService).execute(any(), propertiesArgumentCaptor.capture(), anyInt(), anyInt(),
+					anyBoolean(), anyBoolean(), any());
+			assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_clients"));
+			assertNull(propertiesArgumentCaptor.getValue().getAdditionalProperties().get("user_drivers"));
+			assertNull(fireboltConnection.getSessionProperties().getAdditionalProperties().get("user_clients"));
+			assertNull(fireboltConnection.getSessionProperties().getAdditionalProperties().get("user_drivers"));
+		}
 	}
 
 	@Test
-	@Disabled("System engine is used until engine_url is available")
 	void shouldGetEngineNameFromHost() throws SQLException {
 		connectionProperties.put("engine", "hello");
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertEquals("hello", fireboltConnection.getEngine());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertEquals(engine.getName(), fireboltConnection.getEngine());
+		}
 	}
 
 	@Test
 	void shouldInitNetworkTimeoutWithPropertyByDefault() throws SQLException {
 		connectionProperties.put("socket_timeout_millis", "60");
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertEquals(60, fireboltConnection.getNetworkTimeout());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertEquals(60, fireboltConnection.getNetworkTimeout());
+		}
 	}
 
 	@Test
 	void shouldInitConnectionTimeoutWithPropertyByDefault() throws SQLException {
 		connectionProperties.put("connection_timeout_millis", "50");
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertEquals(50, fireboltConnection.getConnectionTimeout());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			assertEquals(50, fireboltConnection.getConnectionTimeout());
+		}
 	}
 
 	@Test
 	void shouldCloseConnectionWhenAbortingConnection() throws SQLException, InterruptedException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		ExecutorService executorService = Executors.newFixedThreadPool(10);
-		fireboltConnection.abort(executorService);
-		executorService.awaitTermination(1, TimeUnit.SECONDS);
-		assertTrue(fireboltConnection.isClosed());
+		try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+			ExecutorService executorService = Executors.newFixedThreadPool(10);
+			fireboltConnection.abort(executorService);
+			executorService.awaitTermination(1, TimeUnit.SECONDS);
+			assertTrue(fireboltConnection.isClosed());
+		}
 	}
 
 	@Test
 	void shouldRemoveExpiredToken() throws SQLException {
-		FireboltProperties fireboltProperties = FireboltProperties.builder().host("host").path("/db").port(8080)
-				.build();
+		FireboltProperties fireboltProperties = FireboltProperties.builder().host("host").path("/db").port(8080).build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			when(fireboltAuthenticationService.getConnectionTokens("http://host:8080", fireboltProperties))
 					.thenReturn(FireboltConnectionTokens.builder().build());
 			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://hello").build());
 
-			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-			fireboltConnection.removeExpiredTokens();
-			verify(fireboltAuthenticationService).removeConnectionTokens("http://host:8080", fireboltProperties);
+			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+				fireboltConnection.removeExpiredTokens();
+				verify(fireboltAuthenticationService).removeConnectionTokens("http://host:8080", fireboltProperties);
+			}
 		}
 	}
 
@@ -287,10 +282,10 @@ void shouldReturnConnectionTokenWhenAvailable() throws SQLException {
 			when(fireboltAuthenticationService.getConnectionTokens(eq("http://host:8080"), any()))
 					.thenReturn(connectionTokens);
 			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://engineHost").build());
-			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-			verify(fireboltAuthenticationService).getConnectionTokens("http://host:8080", fireboltProperties);
-			assertEquals(accessToken, fireboltConnection.getAccessToken().get());
+			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+				verify(fireboltAuthenticationService).getConnectionTokens("http://host:8080", fireboltProperties);
+				assertEquals(accessToken, fireboltConnection.getAccessToken().get());
+			}
 		}
 	}
 
@@ -300,10 +295,10 @@ void shouldNotReturnConnectionTokenWithLocalDb() throws SQLException {
 				.build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
-			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-			assertEquals(Optional.empty(), fireboltConnection.getAccessToken());
-			verifyNoInteractions(fireboltAuthenticationService);
+			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+				assertEquals(Optional.empty(), fireboltConnection.getAccessToken());
+				verifyNoInteractions(fireboltAuthenticationService);
+			}
 		}
 	}
 
@@ -313,57 +308,53 @@ void shouldSetNetworkTimeout() throws SQLException {
 				.socketTimeoutMillis(5).port(8080).build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
-			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-			assertEquals(5, fireboltConnection.getNetworkTimeout());
-			fireboltConnection.setNetworkTimeout(null, 1);
-			assertEquals(1, fireboltConnection.getNetworkTimeout());
+			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+				assertEquals(5, fireboltConnection.getNetworkTimeout());
+				fireboltConnection.setNetworkTimeout(null, 1);
+				assertEquals(1, fireboltConnection.getNetworkTimeout());
+			}
 		}
 	}
 
 	@Test
 	void shouldUseConnectionTimeoutFromProperties() throws SQLException {
-		FireboltProperties fireboltProperties = FireboltProperties.builder().host("localhost").path("/db")
-				.connectionTimeoutMillis(20).port(8080).build();
+		FireboltProperties fireboltProperties = FireboltProperties.builder().host("localhost").path("/db").connectionTimeoutMillis(20).port(8080).build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
-			FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-					fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-			assertEquals(20, fireboltConnection.getConnectionTimeout());
+			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
+				assertEquals(20, fireboltConnection.getConnectionTimeout());
+			}
 		}
 	}
 
 	@Test
 	void shouldThrowExceptionWhenTryingToUseClosedConnection() throws SQLException {
-		FireboltConnection fireboltConnection = new FireboltConnection(URL, connectionProperties,
-				fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		fireboltConnection.close();
-		assertThrows(FireboltException.class, fireboltConnection::getCatalog);
+		try (Connection connection = createConnection(URL, connectionProperties)) {
+			connection.close();
+			assertThrows(FireboltException.class, connection::getCatalog);
+		}
 	}
 
 	@Test
 	void shouldUnwrapFireboltConnection() throws SQLException {
-		Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService);
-		assertTrue(connection.isWrapperFor(FireboltConnection.class));
-		assertEquals(connection, connection.unwrap(FireboltConnection.class));
+		try (Connection connection = createConnection(URL, connectionProperties)) {
+			assertTrue(connection.isWrapperFor(FireboltConnection.class));
+			assertEquals(connection, connection.unwrap(FireboltConnection.class));
+		}
 	}
 
 	@Test
 	void shouldThrowExceptionWhenCannotUnwrap() throws SQLException {
-		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+		try (Connection connection = createConnection(URL, connectionProperties)) {
 			assertFalse(connection.isWrapperFor(String.class));
 			assertThrows(SQLException.class, () -> connection.unwrap(String.class));
 		}
 	}
 
 	@Test
-	@Disabled("Db is currently not supported")
 	void shouldGetDatabaseWhenGettingCatalog() throws SQLException {
 		connectionProperties.put("database", "db");
-		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+		try (Connection connection = createConnection(URL, connectionProperties)) {
 			assertEquals("db", connection.getCatalog());
 		}
 	}
@@ -371,8 +362,7 @@ void shouldGetDatabaseWhenGettingCatalog() throws SQLException {
 	@Test
 	void shouldGetNoneTransactionIsolation() throws SQLException {
 		connectionProperties.put("database", "db");
-		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+		try (Connection connection = createConnection(URL, connectionProperties)) {
 			assertEquals(Connection.TRANSACTION_NONE, connection.getTransactionIsolation());
 		}
 	}
@@ -380,48 +370,46 @@ void shouldGetNoneTransactionIsolation() throws SQLException {
 	@Test
 	void shouldThrowExceptionWhenPreparingStatementWIthInvalidResultSetType() throws SQLException {
 		connectionProperties.put("database", "db");
-		try (Connection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
+		try (Connection connection = createConnection(URL, connectionProperties)) {
 			assertThrows(SQLFeatureNotSupportedException.class,
 					() -> connection.prepareStatement("any", TYPE_SCROLL_INSENSITIVE, 0));
 		}
 	}
 
 	@Test
-	@Disabled("Disabled until engine_url is available")
 	void shouldGetDefaultEngineWhenEngineIsNotProvided() throws SQLException {
 		connectionProperties.put("engine", "");
 		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().name("default_engine").endpoint("http://my-endpoint").build());
-		try (FireboltConnection  connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
-			verify(fireboltEngineService).getEngine(null, "db");
+		try (FireboltConnection  connection = createConnection(URL, connectionProperties)) {
+			verify(fireboltEngineService).getEngine("", "db");
 			assertEquals("default_engine", connection.getSessionProperties().getEngine());
-			assertEquals("my-endpoint", connection.getSessionProperties().getHost());
+			assertEquals("http://my-endpoint", connection.getSessionProperties().getHost());
 		}
 	}
 
 	@Test
-	@Disabled("Disabled until engine_url is available")
 	void shouldGetEngineUrlWhenEngineIsProvided() throws SQLException {
 		connectionProperties.put("engine", "engine");
 		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("http://my_endpoint").build());
-		try (FireboltConnection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
-			verify(fireboltEngineService).getEngine("engine", null);
+		try (FireboltConnection connection = createConnection(URL, connectionProperties)) {
+			verify(fireboltEngineService).getEngine("engine", "db");
 			assertEquals("http://my_endpoint", connection.getSessionProperties().getHost());
 		}
 	}
 
 	@Test
-	@Disabled("Db is currently not supported")
 	void shouldNotGetEngineUrlOrDefaultEngineUrlWhenUsingSystemEngine() throws SQLException {
 		connectionProperties.put("engine", "system");
+		connectionProperties.put("database", "my_db");
 		when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://my_endpoint");
 
-		try (FireboltConnection connection = new FireboltConnection(URL, connectionProperties, fireboltAuthenticationService,
-				fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService)) {
-			verify(fireboltEngineService, times(0)).getEngine(any(), any());
-			assertEquals("http://my_endpoint", connection.getSessionProperties().getHost());
+		try (FireboltConnection connection = createConnection(URL, connectionProperties)) {
+			verify(fireboltEngineService, times(0)).getEngine(eq("system"), eq("my_db"));
+			assertEquals("my_endpoint", connection.getSessionProperties().getHost());
 		}
 	}
+
+	private FireboltConnection createConnection(String url, Properties props) throws FireboltException {
+		return new FireboltConnection(url, props, fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService, fireboltAccountIdService);
+	}
 }
diff --git a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
index a583c8939..7b2875c6a 100644
--- a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
@@ -15,7 +15,7 @@ void shouldHaveDefaultPropertiesWhenOnlyTheRequiredFieldsAreSpecified() {
 		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().database("db").bufferSize(65536)
 				.sslCertificatePath("").sslMode("strict").path("").port(443) // 443 by default as SSL is enabled by
 				.systemEngine(false).compress(true)													// default
-				.user(null).password(null).host("host").ssl(true).additionalProperties(new HashMap<>())
+				.principal(null).secret(null).host("host").ssl(true).additionalProperties(new HashMap<>())
 				.account(null).keepAliveTimeoutMillis(300000).maxConnectionsTotal(300).maxRetries(3)
 				.socketTimeoutMillis(0).connectionTimeoutMillis(60000).tcpKeepInterval(30).environment("app").tcpKeepIdle(60)
 				.tcpKeepCount(10).account("firebolt").build();
@@ -45,7 +45,7 @@ void shouldHaveAllTheSpecifiedCustomProperties() {
 
 		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().bufferSize(51)
 				.sslCertificatePath("root_cert").sslMode("none").path("example").database("myDb").compress(true)
-				.port(443).user(null).password(null).host("myDummyHost").ssl(true).systemEngine(false)
+				.port(443).principal(null).secret(null).host("myDummyHost").ssl(true).systemEngine(false)
 				.additionalProperties(customProperties).account(null).keepAliveTimeoutMillis(300000)
 				.maxConnectionsTotal(300).maxRetries(3).socketTimeoutMillis(20).connectionTimeoutMillis(60000)
 				.tcpKeepInterval(30).tcpKeepIdle(60).tcpKeepCount(10).environment("app").account("firebolt").build();
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
index 2a8700549..8c794388a 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltAuthenticationServiceTest.java
@@ -28,8 +28,7 @@ class FireboltAuthenticationServiceTest {
 
 	private static final String ENV = "ENV";
 
-	private static final FireboltProperties PROPERTIES = FireboltProperties.builder().user(USER).password(PASSWORD).environment(ENV)
-			.compress(true).build();
+	private static final FireboltProperties PROPERTIES = FireboltProperties.builder().principal(USER).secret(PASSWORD).environment(ENV).compress(true).build();
 
 	@Mock
 	private FireboltAuthenticationClient fireboltAuthenticationClient;
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
index 37dd345ba..412ee2daa 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
@@ -1,24 +1,23 @@
 package com.firebolt.jdbc.service;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
+import com.firebolt.jdbc.connection.Engine;
+import com.firebolt.jdbc.connection.FireboltConnection;
+import com.firebolt.jdbc.exception.FireboltException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 
-import com.firebolt.jdbc.connection.Engine;
-import com.firebolt.jdbc.connection.FireboltConnection;
-import com.firebolt.jdbc.exception.FireboltException;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 @ExtendWith(MockitoExtension.class)
 class FireboltEngineServiceTest {
@@ -46,50 +45,50 @@ void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromNullHost() {
 
 	@Test
 	void shouldGetDefaultEngineWhenEngineNameIsNotProvided() throws SQLException {
-		Statement statement = mock(Statement.class);
+		PreparedStatement statement = mock(PreparedStatement.class);
 		ResultSet resultSet = mock(ResultSet.class);
 		when(resultSet.next()).thenReturn(true);
 		when(resultSet.getString("status")).thenReturn("running");
-		when(resultSet.getString("engine_url")).thenReturn("https://url");
+		when(resultSet.getString("url")).thenReturn("https://url");
 		when(resultSet.getString("engine_name")).thenReturn("hello-engine");
-		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
-		when(statement.executeQuery(any())).thenReturn(resultSet);
+		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
+		when(statement.executeQuery()).thenReturn(resultSet);
 		assertEquals(Engine.builder().endpoint("https://url").name("hello-engine").build(),
 				fireboltEngineService.getEngine(null, "db"));
 	}
 
 	@Test
 	void shouldThrowExceptionWhenDefaultEngineNotRunning() throws SQLException {
-		Statement statement = mock(Statement.class);
+		PreparedStatement statement = mock(PreparedStatement.class);
 		ResultSet resultSet = mock(ResultSet.class);
 		when(resultSet.next()).thenReturn(true);
 		when(resultSet.getString("status")).thenReturn("down");
-		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
-		when(statement.executeQuery(any())).thenReturn(resultSet);
+		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
+		when(statement.executeQuery()).thenReturn(resultSet);
 		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(null, "db"));
 	}
 
 	@Test
 	void shouldGetEngineWhenEngineNameIsProvided() throws SQLException {
-		Statement statement = mock(Statement.class);
+		PreparedStatement statement = mock(PreparedStatement.class);
 		ResultSet resultSet = mock(ResultSet.class);
 		when(resultSet.next()).thenReturn(true);
 		when(resultSet.getString("status")).thenReturn("running");
-		when(resultSet.getString("engine_url")).thenReturn("https://url");
-		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
-		when(statement.executeQuery(any())).thenReturn(resultSet);
+		when(resultSet.getString("url")).thenReturn("https://url");
+		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
+		when(statement.executeQuery()).thenReturn(resultSet);
 		assertEquals(Engine.builder().endpoint("https://url").name("some-engine").build(),
 				fireboltEngineService.getEngine("some-engine", "db"));
 	}
 
 	@Test
 	void shouldThrowExceptionWhenEngineNotRunning() throws SQLException {
-		Statement statement = mock(Statement.class);
+		PreparedStatement statement = mock(PreparedStatement.class);
 		ResultSet resultSet = mock(ResultSet.class);
 		when(resultSet.next()).thenReturn(true);
 		when(resultSet.getString("status")).thenReturn("down");
-		when(fireboltConnection.createSystemEngineStatementStatement()).thenReturn(statement);
-		when(statement.executeQuery(any())).thenReturn(resultSet);
+		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
+		when(statement.executeQuery()).thenReturn(resultSet);
 		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine("some-engine", "db"));
 	}
 

From 5ecf60f2bd663be6ae3a5ab66bcb2fcd6c257f25 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Sun, 9 Jul 2023 15:35:15 +0300
Subject: [PATCH 03/15] applied pr comments

---
 .github/workflows/integration-test.yml        |  6 ++++-
 .../integration/tests/NumericTypesTest.java   | 24 +++++++++++++++++++
 .../integration/tests/SystemEngineTest.java   |  2 +-
 .../java/com/firebolt/FireboltDriver.java     |  3 +--
 .../firebolt/jdbc/client/FireboltClient.java  |  7 +++---
 .../account/FireboltAccountRetriever.java     | 10 ++++----
 .../FireboltAuthenticationClient.java         |  2 +-
 .../client/query/StatementClientImpl.java     |  6 ++---
 .../jdbc/connection/FireboltConnection.java   | 12 ++++++----
 .../settings/FireboltProperties.java          | 22 +++++++++++++++--
 .../gateway/FireboltGatewayUrlClientTest.java |  4 ++--
 .../client/query/StatementClientImplTest.java | 12 +++++-----
 .../settings/FireboltPropertiesTest.java      | 24 +++++++++++++++++++
 13 files changed, 103 insertions(+), 31 deletions(-)
 create mode 100644 src/integrationTest/java/integration/tests/NumericTypesTest.java

diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index 21cd1a41a..5f4d34bed 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -7,9 +7,13 @@ on:
         description: 'Database - a new one will be created if not provided'
         required: false
         default: ''
+      engine:
+        description: 'Engine'
+        required: true
       account:
         description: 'Account'
         required: true
+        default: 'integration'
       environment:
         description: 'Environment to run the tests against'
         type: choice
@@ -69,7 +73,7 @@ jobs:
           fi
 
       - name: Run integration tests
-        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dpassword="${{ env.SERVICE_ACCOUNT_SECRET }}" -Duser="${{ env.SERVICE_ACCOUNT_ID }} -Daccount=${{ github.event.inputs.account }}"
+        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }} -Daccount=${{ github.event.inputs.account }}" -Dengine=${{ github.event.inputs.engine }}"
 
       - name: "Foresight: Analyze Test Results"
         uses: runforesight/foresight-test-kit-action@v1
diff --git a/src/integrationTest/java/integration/tests/NumericTypesTest.java b/src/integrationTest/java/integration/tests/NumericTypesTest.java
new file mode 100644
index 000000000..c0c2dda5b
--- /dev/null
+++ b/src/integrationTest/java/integration/tests/NumericTypesTest.java
@@ -0,0 +1,24 @@
+package integration.tests;
+
+import integration.IntegrationTest;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class NumericTypesTest extends IntegrationTest {
+    @Test
+    void shouldHaveCorrectInfo() throws SQLException {
+        try (Connection connection = this.createConnection("system");
+             Statement statement = connection.createStatement();
+             ResultSet resultSet = statement.executeQuery("SELECT 3::decimal")) {
+            resultSet.next();
+            assertEquals(9, resultSet.getMetaData().getScale(1));
+            assertEquals(38, resultSet.getMetaData().getPrecision(1));
+        }
+    }
+}
diff --git a/src/integrationTest/java/integration/tests/SystemEngineTest.java b/src/integrationTest/java/integration/tests/SystemEngineTest.java
index 80870eade..cd596d09d 100644
--- a/src/integrationTest/java/integration/tests/SystemEngineTest.java
+++ b/src/integrationTest/java/integration/tests/SystemEngineTest.java
@@ -41,7 +41,7 @@ void afterAll() {
 	@Test
 	void shouldExecuteQueriesUsingSystemEngine() throws SQLException {
 		try (Connection connection = this.createConnection(SYSTEM_ENGINE_NAME)) {
-			List<String> queries = Arrays.asList(String.format("CREATE DATABASE %s", DATABASE_NAME),
+			List<String> queries = Arrays.asList(String.format("CREATE DATABASE IF NOT EXISTS %s", DATABASE_NAME),
 					String.format("CREATE ENGINE %s", ENGINE_NAME),
 					String.format("ATTACH ENGINE %s TO %s;", ENGINE_NAME, DATABASE_NAME),
 					String.format("ALTER DATABASE %s WITH DESCRIPTION = 'JDBC Integration test'", DATABASE_NAME),
diff --git a/src/main/java/com/firebolt/FireboltDriver.java b/src/main/java/com/firebolt/FireboltDriver.java
index 15e248c1b..1794d615b 100644
--- a/src/main/java/com/firebolt/FireboltDriver.java
+++ b/src/main/java/com/firebolt/FireboltDriver.java
@@ -17,7 +17,6 @@
 public class FireboltDriver implements Driver {
 
 	public static final String JDBC_FIREBOLT = "jdbc:firebolt:";
-	private static final String JDBC_FIREBOLT_PREFIX = JDBC_FIREBOLT;
 
 	static {
 		try {
@@ -35,7 +34,7 @@ public Connection connect(String url, Properties connectionSettings) throws SQLE
 
 	@Override
 	public boolean acceptsURL(String url) {
-		return StringUtils.isNotEmpty(url) && url.startsWith(JDBC_FIREBOLT_PREFIX);
+		return StringUtils.isNotEmpty(url) && url.startsWith(JDBC_FIREBOLT);
 	}
 
 	@Override
diff --git a/src/main/java/com/firebolt/jdbc/client/FireboltClient.java b/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
index a520f12f5..aab78cc55 100644
--- a/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
+++ b/src/main/java/com/firebolt/jdbc/client/FireboltClient.java
@@ -32,16 +32,15 @@ public abstract class FireboltClient {
 	public static final String HEADER_AUTHORIZATION = "Authorization";
 	public static final String HEADER_AUTHORIZATION_BEARER_PREFIX_VALUE = "Bearer ";
 	public static final String HEADER_USER_AGENT = "User-Agent";
+	private final OkHttpClient httpClient;
 	protected final ObjectMapper objectMapper;
 	private final String headerUserAgentValue;
-	private final OkHttpClient httpClient;
 	private final FireboltConnection connection;
 
-	protected FireboltClient(OkHttpClient httpClient, FireboltConnection connection, String customDrivers,
-			String customClients, ObjectMapper objectMapper) {
+	protected FireboltClient(OkHttpClient httpClient, ObjectMapper objectMapper, FireboltConnection connection, String customDrivers, String customClients) {
 		this.httpClient = httpClient;
-		this.connection = connection;
 		this.objectMapper = objectMapper;
+		this.connection = connection;
 		this.headerUserAgentValue = UsageTrackerUtil.getUserAgentString(customDrivers != null ? customDrivers : "",
 				customClients != null ? customClients : "");
 	}
diff --git a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
index cc7936877..c99efc6f7 100644
--- a/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
+++ b/src/main/java/com/firebolt/jdbc/client/account/FireboltAccountRetriever.java
@@ -11,19 +11,21 @@
 import static java.lang.String.format;
 
 public class FireboltAccountRetriever<T> extends FireboltClient {
-    private static final String URL = "https://api.dev.firebolt.io/web/v3/account/%s/%s";
+    private static final String URL = "https://%s/web/v3/account/%s/%s";
+    private final String host;
     private final String path;
     private final Class<T> type;
 
-    public FireboltAccountRetriever(OkHttpClient httpClient, FireboltConnection connection, String customDrivers, String customClients, ObjectMapper objectMapper, String path, Class<T> type) {
-        super(httpClient, connection, customDrivers, customClients, objectMapper);
+    public FireboltAccountRetriever(OkHttpClient httpClient, ObjectMapper objectMapper, FireboltConnection connection, String customDrivers, String customClients, String host, String path, Class<T> type) {
+        super(httpClient, objectMapper, connection, customDrivers, customClients);
+        this.host = host;
         this.path = path;
         this.type = type;
     }
 
     public T retrieve(String accessToken, String accountName) throws FireboltException {
         try {
-            return getResource(format(URL, accountName, path), accessToken, type);
+            return getResource(format(URL, host, accountName, path), accessToken, type);
         } catch (IOException e) {
             throw new FireboltException(String.format("Failed to get %s url for account %s", path, accountName), e);
         }
diff --git a/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java b/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
index a63d00747..d9a9cb30b 100644
--- a/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
+++ b/src/main/java/com/firebolt/jdbc/client/authentication/FireboltAuthenticationClient.java
@@ -21,7 +21,7 @@ public class FireboltAuthenticationClient extends FireboltClient {
 
 	public FireboltAuthenticationClient(OkHttpClient httpClient, ObjectMapper objectMapper,
 			FireboltConnection connection, String customDrivers, String customClients) {
-		super(httpClient, connection, customDrivers, customClients, objectMapper);
+		super(httpClient, objectMapper, connection, customDrivers, customClients);
 	}
 
 	/**
diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index b23464ca9..83a8ac740 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -42,9 +42,8 @@ public class StatementClientImpl extends FireboltClient implements StatementClie
 	private final BiPredicate<Call, String> isCallWithId = (call, id) -> call.request().tag() instanceof String
 			&& StringUtils.equals((String) call.request().tag(), id);
 
-	public StatementClientImpl(OkHttpClient httpClient, FireboltConnection connection, ObjectMapper objectMapper,
-			String customDrivers, String customClients) {
-		super(httpClient, connection, customDrivers, customClients, objectMapper);
+	public StatementClientImpl(OkHttpClient httpClient, ObjectMapper objectMapper, FireboltConnection connection, String customDrivers, String customClients) {
+		super(httpClient, objectMapper, connection, customDrivers, customClients);
 	}
 
 	/**
@@ -208,7 +207,6 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 		if (systemEngine) {
 			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId()); // "01h11x0zmecanh1vp2q1mar5nh"
 		} else {
-			// System engines do not support the following query params
 			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
 			params.put(FireboltQueryParameterKey.QUERY_ID.getKey(), statementInfoWrapper.getId());
 			params.put(FireboltQueryParameterKey.COMPRESS.getKey(), fireboltProperties.isCompress() ? "1" : "0");
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index 26acdcd3d..73e2a8975 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -78,7 +78,7 @@ public FireboltConnection(@NonNull String url, Properties connectionSettings,
 		this.connect();
 	}
 
-	// This ugly code duplication between constructors is done because of back reference: dependent services require reference to current instance of FireboltConnection that prevents using constructor chaining or factory method.
+	// This code duplication between constructors is done because of back reference: dependent services require reference to current instance of FireboltConnection that prevents using constructor chaining or factory method.
 	@ExcludeFromJacocoGeneratedReport
 	public FireboltConnection(@NonNull String url, Properties connectionSettings) throws FireboltException {
 		this.loginProperties = extractFireboltProperties(url, connectionSettings);
@@ -86,16 +86,16 @@ public FireboltConnection(@NonNull String url, Properties connectionSettings) th
 		ObjectMapper objectMapper = FireboltObjectMapper.getInstance();
 
 		this.fireboltAuthenticationService = new FireboltAuthenticationService(new FireboltAuthenticationClient(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
-		this.fireboltGatewayUrlService = new FireboltGatewayUrlService(new FireboltAccountRetriever<>(httpClient, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), objectMapper, "engineUrl", GatewayUrlResponse.class));
+		this.fireboltGatewayUrlService = new FireboltGatewayUrlService(createFireboltAccountRetriever(httpClient, objectMapper, "engineUrl", GatewayUrlResponse.class));
 		this.httpConnectionUrl = getHttpConnectionUrl(loginProperties);
-		this.fireboltStatementService = new FireboltStatementService(new StatementClientImpl(httpClient, this, objectMapper, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
+		this.fireboltStatementService = new FireboltStatementService(new StatementClientImpl(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients()));
 
 		this.statements = new ArrayList<>();
 		this.connectionTimeout = loginProperties.getConnectionTimeoutMillis();
 		this.networkTimeout = loginProperties.getSocketTimeoutMillis();
 		this.systemEngine = loginProperties.isSystemEngine();
 		this.fireboltEngineService = new FireboltEngineService(this);
-		this.fireboltAccountIdService = new FireboltAccountIdService(new FireboltAccountRetriever<>(httpClient, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), objectMapper, "resolve", FireboltAccount.class));
+		this.fireboltAccountIdService = new FireboltAccountIdService(createFireboltAccountRetriever(httpClient, objectMapper, "resolve", FireboltAccount.class));
 
 		this.connect();
 	}
@@ -108,6 +108,10 @@ private static OkHttpClient getHttpClient(FireboltProperties fireboltProperties)
 		}
 	}
 
+	private <T> FireboltAccountRetriever<T> createFireboltAccountRetriever(OkHttpClient httpClient, ObjectMapper objectMapper, String path, Class<T> type) {
+		return new FireboltAccountRetriever<>(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), loginProperties.getHost(), path, type);
+	}
+
 	private void connect() throws FireboltException {
 		String accessToken = this.getAccessToken(loginProperties).orElse(StringUtils.EMPTY);
 		closed = false;
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index 8f523a117..7023d271d 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -11,6 +11,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @Value
 @Builder(toBuilder = true)
@@ -87,11 +88,12 @@ public static FireboltProperties of(Properties... properties) {
 		int tcpKeepIdle = getSetting(mergedProperties, FireboltSessionProperty.TCP_KEEP_IDLE);
 		int tcpKeepCount = getSetting(mergedProperties, FireboltSessionProperty.TCP_KEEP_COUNT);
 		boolean logResultSet = getSetting(mergedProperties, FireboltSessionProperty.LOG_RESULT_SET);
-		String environment = getSetting(mergedProperties, FireboltSessionProperty.ENVIRONMENT);
+		String configuredEnvironment = getSetting(mergedProperties, FireboltSessionProperty.ENVIRONMENT);
 		String driverVersions = getSetting(mergedProperties, FireboltSessionProperty.USER_DRIVERS);
 		String clientVersions = getSetting(mergedProperties, FireboltSessionProperty.USER_CLIENTS);
 
-		String host = getHost(environment, mergedProperties);
+		String environment = getEnvironment(configuredEnvironment, mergedProperties);
+		String host = getHost(configuredEnvironment, mergedProperties);
 		Integer port = getPort(mergedProperties, ssl);
 
 		Map<String, String> additionalProperties = getFireboltCustomProperties(mergedProperties);
@@ -127,6 +129,22 @@ private static String getHost(String environment, Properties properties ) {
 		}
 	}
 
+	private static String getEnvironment(String environment, Properties properties ) {
+		Pattern environmentalHost = Pattern.compile("api\\.(.+?)\\.firebolt\\.io");
+		if (Objects.equals(environment, FireboltSessionProperty.ENVIRONMENT.getDefaultValue())) {
+			if (Stream.concat(Stream.of(FireboltSessionProperty.ENVIRONMENT.getKey()), Stream.of(FireboltSessionProperty.ENVIRONMENT.getAliases())).noneMatch(properties::containsKey)) {
+				String host = getSetting(properties, FireboltSessionProperty.HOST);
+				if (host != null) {
+					Matcher m = environmentalHost.matcher(host);
+					if (m.find() && m.group(1) != null) {
+						return m.group(1);
+					}
+				}
+			}
+		}
+		return environment;
+	}
+
 	@NonNull
 	private static Integer getPort(Properties properties, boolean ssl) {
 		Integer port = getSetting(properties, FireboltSessionProperty.PORT);
diff --git a/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
index 4fcb1639c..d00021b4b 100644
--- a/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/gateway/FireboltGatewayUrlClientTest.java
@@ -43,8 +43,8 @@ class FireboltAccountRetrieverTest {
 
     @BeforeEach
     void setUp() {
-        fireboltGatewayUrlClient = new FireboltAccountRetriever<>(httpClient, fireboltConnection, null, null, objectMapper, "engineUrl", GatewayUrlResponse.class);
-        fireboltAccountIdResolver = new FireboltAccountRetriever<>(httpClient, fireboltConnection, null, null, objectMapper, "resolve", FireboltAccount.class);
+        fireboltGatewayUrlClient = new FireboltAccountRetriever<>(httpClient, objectMapper, fireboltConnection, null, null, "http://test-firebolt.io", "engineUrl", GatewayUrlResponse.class);
+        fireboltAccountIdResolver = new FireboltAccountRetriever<>(httpClient, objectMapper, fireboltConnection, null, null, "http://test-firebolt.io", "resolve", FireboltAccount.class);
     }
 
 	@Test
diff --git a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
index 425080211..3fba163c9 100644
--- a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
@@ -50,7 +50,7 @@ void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 				.thenReturn(Optional.of("token"));
 
 		injectMockedResponse(okHttpClient, 200);
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
+		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
 				"ConnA:1.0.9", "ConnB:2.0.9");
 		Call call = getMockedCallWithResponse(200);
 		when(okHttpClient.newCall(any())).thenReturn(call);
@@ -77,7 +77,7 @@ void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException,
 				.host("firebolt1").port(555).accountId("12345").build();
 		when(connection.getAccessToken())
 				.thenReturn(Optional.of("token"));
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
+		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
 				"ConnA:1.0.9", "ConnB:2.0.9");
 		injectMockedResponse(okHttpClient, 200);
 		Call call = getMockedCallWithResponse(200);
@@ -98,8 +98,8 @@ void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException,
 	void shouldCancelSqlQuery() throws FireboltException, IOException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db1").compress(true)
 				.host("firebolt1").port(555).build();
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection,
-				mock(ObjectMapper.class), "", "");
+		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
+				"", "");
 		injectMockedResponse(okHttpClient, 200);
 		Call call = getMockedCallWithResponse(200);
 		when(okHttpClient.newCall(any())).thenReturn(call);
@@ -118,7 +118,7 @@ void shouldRetryOnUnauthorized() throws IOException, FireboltException {
 		Call okCall = getMockedCallWithResponse(200);
 		Call unauthorizedCall = getMockedCallWithResponse(401);
 		when(okHttpClient.newCall(any())).thenReturn(unauthorizedCall).thenReturn(okCall);
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
+		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
 				"ConnA:1.0.9", "ConnB:2.0.9");
 		StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("show databases").get(0);
 		statementClient.executeSqlStatement(statementInfoWrapper, fireboltProperties, false, 5, 5, true);
@@ -135,7 +135,7 @@ void shouldNotRetryNoMoreThanOnceOnUnauthorized() throws IOException, FireboltEx
 		Call okCall = getMockedCallWithResponse(200);
 		Call unauthorizedCall = getMockedCallWithResponse(401);
 		when(okHttpClient.newCall(any())).thenReturn(unauthorizedCall).thenReturn(unauthorizedCall).thenReturn(okCall);
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, connection, mock(ObjectMapper.class),
+		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
 				"ConnA:1.0.9", "ConnB:2.0.9");
 		StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("show databases").get(0);
 		FireboltException ex = assertThrows(FireboltException.class, () -> statementClient.executeSqlStatement(statementInfoWrapper, fireboltProperties, false, 5, 5, true));
diff --git a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
index 7b2875c6a..9610bf9f3 100644
--- a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
@@ -7,6 +7,8 @@
 import java.util.Properties;
 
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 class FireboltPropertiesTest {
 
@@ -152,4 +154,26 @@ void shouldSupportUserClientsAndDrivers() {
 		assertEquals(drivers, FireboltProperties.of(properties).getUserDrivers());
 	}
 
+	@ParameterizedTest
+	@CsvSource(value = {
+			"env, qa,,api.qa.firebolt.io,qa",
+			"environment, test,,api.test.firebolt.io,test",
+			"env, staging,super-host.com,super-host.com,staging",
+			"env,,my-host.com,my-host.com,app",
+			"env,,api.dev.firebolt.io,api.dev.firebolt.io,dev",
+			"env,,something.io,something.io,app", // not standard host, no configured environment -> default environment
+			",,,api.app.firebolt.io,app", // no host, no environment -> default environment (app) and default host api.app.firebolt.io
+	}, delimiter = ',')
+	void hostAndEnvironment(String envKey, String envValue, String host, String expectedHost, String expectedEnvironment) {
+		Properties properties = new Properties();
+		if (envValue != null) {
+			properties.put(envKey, envValue);
+		}
+		if (host != null) {
+			properties.put("host", host);
+		}
+		assertEquals(expectedHost, FireboltProperties.of(properties).getHost());
+		assertEquals(expectedEnvironment, FireboltProperties.of(properties).getEnvironment());
+	}
+
 }

From f15c62a55d862bb1c18b8f0e17e500c5ebc45dbd Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Sun, 9 Jul 2023 17:57:57 +0300
Subject: [PATCH 04/15] fixed command line of integration tests

---
 .github/workflows/integration-test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index 5f4d34bed..435b29282 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -73,7 +73,7 @@ jobs:
           fi
 
       - name: Run integration tests
-        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }} -Daccount=${{ github.event.inputs.account }}" -Dengine=${{ github.event.inputs.engine }}"
+        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }} -Daccount="${{ github.event.inputs.account }}" -Dengine="${{ github.event.inputs.engine }}"
 
       - name: "Foresight: Analyze Test Results"
         uses: runforesight/foresight-test-kit-action@v1

From 8859c86e78faf3c5268f4f6d9d29172c76e10b8d Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Sun, 9 Jul 2023 18:03:34 +0300
Subject: [PATCH 05/15] fixed command line of integration tests

---
 .github/workflows/integration-test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index 435b29282..d6148db1e 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -73,7 +73,7 @@ jobs:
           fi
 
       - name: Run integration tests
-        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }} -Daccount="${{ github.event.inputs.account }}" -Dengine="${{ github.event.inputs.engine }}"
+        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }}" -Daccount="${{ github.event.inputs.account }}" -Dengine="${{ github.event.inputs.engine }}"
 
       - name: "Foresight: Analyze Test Results"
         uses: runforesight/foresight-test-kit-action@v1

From 08f6efa7955859aa1d356f11dda58b653d04a720 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Sun, 9 Jul 2023 19:10:24 +0300
Subject: [PATCH 06/15] removed test that has been already move to another
 testcase

---
 .../java/integration/tests/TimestampTest.java        | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/src/integrationTest/java/integration/tests/TimestampTest.java b/src/integrationTest/java/integration/tests/TimestampTest.java
index a62b8bb6e..ee3f671f7 100644
--- a/src/integrationTest/java/integration/tests/TimestampTest.java
+++ b/src/integrationTest/java/integration/tests/TimestampTest.java
@@ -131,18 +131,6 @@ void shouldRemoveOffsetDIffWhenTimestampOffsetHasChangedCET() throws SQLExceptio
 		}
 	}
 
-	@Test
-	void shouldHaveCorrectInfo() throws SQLException {
-		try (Connection connection = this.createConnection("system");
-			 Statement statement = connection.createStatement();
-			 ResultSet resultSet = statement.executeQuery("SELECT 3::decimal")) {
-			 resultSet.next();
-			 assertEquals(9, resultSet.getMetaData().getScale(1));
-			assertEquals(38, resultSet.getMetaData().getPrecision(1));
-		}
-
-	}
-
 	@Test
 	void shouldReturnTimestampFromTimestampntz() throws SQLException {
 		try (Connection connection = this.createConnection();

From cc1c7f60d07976147b746d1e223a2ebd23d3a240 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Mon, 10 Jul 2023 19:30:55 +0300
Subject: [PATCH 07/15] applied PR comments

---
 .../java/integration/ConnectionInfo.java      |  1 +
 .../jdbc/connection/FireboltConnection.java   |  2 +-
 .../settings/FireboltProperties.java          | 49 ++++++++++-------
 .../settings/FireboltSessionProperty.java     |  6 ++-
 .../jdbc/service/FireboltEngineService.java   |  2 +-
 .../connection/FireboltConnectionTest.java    | 12 +++++
 .../settings/FireboltPropertiesTest.java      | 34 +++++++++---
 .../service/FireboltEngineServiceTest.java    | 53 +++++++++----------
 8 files changed, 104 insertions(+), 55 deletions(-)

diff --git a/src/integrationTest/java/integration/ConnectionInfo.java b/src/integrationTest/java/integration/ConnectionInfo.java
index d9d527eeb..5e88373b5 100644
--- a/src/integrationTest/java/integration/ConnectionInfo.java
+++ b/src/integrationTest/java/integration/ConnectionInfo.java
@@ -6,6 +6,7 @@
 
 public class ConnectionInfo {
 	private static volatile ConnectionInfo INSTANCE;
+	// principal and secret are used here instead of client_id and client_secret respectively as more common term also used in java security API.
 	private final String principal;
 	private final String secret;
 	private final String env;
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index 73e2a8975..a7c7c56e8 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -117,7 +117,7 @@ private void connect() throws FireboltException {
 		closed = false;
 		if (!PropertyUtil.isLocalDb(loginProperties)) {
 			internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, loginProperties.getAccount());
-			String accountId =  fireboltAccountIdService.getValue(accessToken, loginProperties.getAccount());
+			String accountId = fireboltAccountIdService.getValue(accessToken, loginProperties.getAccount());
 			if (!loginProperties.isSystemEngine()) {
 				sessionProperties = internalSystemEngineProperties.toBuilder()
 						.engine(loginProperties.getEngine())
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index 7023d271d..b79e4eeab 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -6,6 +6,7 @@
 import lombok.Value;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
+import org.jetbrains.annotations.NotNull;
 
 import java.util.*;
 import java.util.regex.Matcher;
@@ -13,6 +14,8 @@
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static java.lang.String.format;
+
 @Value
 @Builder(toBuilder = true)
 @CustomLog
@@ -56,7 +59,6 @@ public class FireboltProperties {
 	Integer tcpKeepInterval;
 	boolean logResultSet;
 	boolean systemEngine;
-	String organization;
 	String environment;
 	String userDrivers;
 	String userClients;
@@ -123,23 +125,39 @@ private static String getEngine(Properties mergedProperties, String database) {
 	private static String getHost(String environment, Properties properties ) {
 		String host = getSetting(properties, FireboltSessionProperty.HOST);
 		if (StringUtils.isEmpty(host)) {
-			return String.format("api.%s.firebolt.io", environment);
+			return format("api.%s.firebolt.io", environment);
 		} else {
 			return host;
 		}
 	}
 
-	private static String getEnvironment(String environment, Properties properties ) {
+	/**
+	 * Discovers environment name from host if it matches pattern {@code api.ENV.firebolt.io}
+	 * @param environment - the environment from properties or default value as defined in {@link FireboltSessionProperty#ENVIRONMENT}
+	 * @param properties - configuration properties
+	 * @return the environment value
+	 * @throws IllegalStateException if environment extracted from host is not equal to given one.
+	 */
+	private static String getEnvironment(String environment, @NotNull Properties properties) {
 		Pattern environmentalHost = Pattern.compile("api\\.(.+?)\\.firebolt\\.io");
-		if (Objects.equals(environment, FireboltSessionProperty.ENVIRONMENT.getDefaultValue())) {
-			if (Stream.concat(Stream.of(FireboltSessionProperty.ENVIRONMENT.getKey()), Stream.of(FireboltSessionProperty.ENVIRONMENT.getAliases())).noneMatch(properties::containsKey)) {
-				String host = getSetting(properties, FireboltSessionProperty.HOST);
-				if (host != null) {
-					Matcher m = environmentalHost.matcher(host);
-					if (m.find() && m.group(1) != null) {
-						return m.group(1);
-					}
-				}
+		String envFromProps = Stream.concat(Stream.of(FireboltSessionProperty.ENVIRONMENT.getKey()), Stream.of(FireboltSessionProperty.ENVIRONMENT.getAliases()))
+				.map(properties::getProperty)
+				.filter(Objects::nonNull).findFirst()
+				.orElse(null);
+		String envFromHost = null;
+		String host = getSetting(properties, FireboltSessionProperty.HOST);
+		if (host != null) {
+			Matcher m = environmentalHost.matcher(host);
+			if (m.find() && m.group(1) != null) {
+				envFromHost = m.group(1);
+			}
+		}
+		if (envFromHost != null) {
+			if (envFromProps == null) {
+				return envFromHost;
+			}
+			if (!Objects.equals(environment, envFromHost)) {
+				throw new IllegalStateException(format("Environment %s does not match host %s", environment, host));
 			}
 		}
 		return environment;
@@ -164,7 +182,7 @@ private static String getDatabase(Properties properties, String path) throws Ill
 				if (m.matches()) {
 					return m.group(1);
 				} else {
-					throw new IllegalArgumentException(String.format("The database provided is invalid %s", path));
+					throw new IllegalArgumentException(format("The database provided is invalid %s", path));
 				}
 			}
 		} else {
@@ -233,9 +251,4 @@ public void addProperty(@NonNull String key, String value) {
 	public void addProperty(Pair<String, String> property) {
 		this.addProperty(property.getLeft(), property.getRight());
 	}
-
-	public static FireboltProperties toSystemEngineProperties(FireboltProperties properties) {
-		return properties.toBuilder().additionalProperties(new HashMap<>(properties.getAdditionalProperties())).build();
-	}
-
 }
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
index 3690f90f4..08212a3ba 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltSessionProperty.java
@@ -44,8 +44,10 @@ public enum FireboltSessionProperty {
 				 */
 			"compress", true, Boolean.class, "Whether to compress transferred data or not. Compressed by default"),
 	DATABASE("database", null, String.class, "default database name"),
-	CLIENT_SECRET("client_secret", null, String.class, "user password - null by default", "password"),
-	CLIENT_ID("client_id", null, String.class, "user name - null by default", "user"),
+	// Typically client_secret property should be used, but password is the standard JDBC property supported by all tools, so it is silently defined here as alias. Also see CLIENT_ID.
+	CLIENT_SECRET("client_secret", null, String.class, "client secret - null by default", "password"),
+	// Typically client_id property should be used, but user is the standard JDBC property supported by all tools, so it is silently defined here as alias. Also see CLIENT_SECRET
+	CLIENT_ID("client_id", null, String.class, "client ID - null by default", "user"),
 	HOST("host", null, String.class, "Firebolt host - null by default"),
 	PORT("port", null, Integer.class, "Firebolt port - null by default"),
 	ENGINE("engine", null, String.class, "engine - null by default", "engine_name"),
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
index ed562548d..ee009cc9c 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
@@ -49,7 +49,7 @@ public String getEngineNameByHost(String engineHost) throws FireboltException {
 
     public Engine getEngine(@Nullable String name, @Nullable String database) throws FireboltException {
         if (StringUtils.isEmpty(name)) {
-            return this.getDefaultEngine(database);
+            return getDefaultEngine(database);
         } else {
             return Engine.builder().name(name).endpoint(getEngineEndpoint(name)).build();
         }
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index 509ef5f26..737aed831 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -409,6 +409,18 @@ void shouldNotGetEngineUrlOrDefaultEngineUrlWhenUsingSystemEngine() throws SQLEx
 		}
 	}
 
+	@Test
+	void noEngineAndDb() throws SQLException {
+		when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://my_endpoint");
+
+		try (FireboltConnection connection = createConnection("jdbc:firebolt:?env=dev", connectionProperties)) {
+			assertEquals("my_endpoint", connection.getSessionProperties().getHost());
+			assertEquals("system", connection.getSessionProperties().getEngine());
+			assertTrue(connection.getSessionProperties().isSystemEngine());
+		}
+	}
+
+
 	private FireboltConnection createConnection(String url, Properties props) throws FireboltException {
 		return new FireboltConnection(url, props, fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService, fireboltAccountIdService);
 	}
diff --git a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
index 9610bf9f3..eefa17ef9 100644
--- a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
@@ -1,14 +1,14 @@
 package com.firebolt.jdbc.connection.settings;
 
-import static org.junit.jupiter.api.Assertions.*;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
 
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.CsvSource;
+import static org.junit.jupiter.api.Assertions.*;
 
 class FireboltPropertiesTest {
 
@@ -154,6 +154,11 @@ void shouldSupportUserClientsAndDrivers() {
 		assertEquals(drivers, FireboltProperties.of(properties).getUserDrivers());
 	}
 
+	@Test
+	void noEngineNoDbSystemEngine() {
+		assertEquals("system", FireboltProperties.of(new Properties()).getEngine());
+	}
+
 	@ParameterizedTest
 	@CsvSource(value = {
 			"env, qa,,api.qa.firebolt.io,qa",
@@ -163,8 +168,26 @@ void shouldSupportUserClientsAndDrivers() {
 			"env,,api.dev.firebolt.io,api.dev.firebolt.io,dev",
 			"env,,something.io,something.io,app", // not standard host, no configured environment -> default environment
 			",,,api.app.firebolt.io,app", // no host, no environment -> default environment (app) and default host api.app.firebolt.io
+			",,api.app.firebolt.io,api.app.firebolt.io,app", // no configured environment, discover default environment from host
+			",,api.dev.firebolt.io,api.dev.firebolt.io,dev", // no configured environment, discover not default environment from host
 	}, delimiter = ',')
 	void hostAndEnvironment(String envKey, String envValue, String host, String expectedHost, String expectedEnvironment) {
+		Properties properties = properties(envKey, envValue, host);
+		assertEquals(expectedHost, FireboltProperties.of(properties).getHost());
+		assertEquals(expectedEnvironment, FireboltProperties.of(properties).getEnvironment());
+	}
+
+	@ParameterizedTest
+	@CsvSource(value = {
+			"env,app,api.dev.firebolt.io",
+			"env,qa,api.app.firebolt.io",
+	}, delimiter = ',')
+	void environmentDoesNotMatch(String envKey, String envValue, String host) {
+		Properties properties = properties(envKey, envValue, host);
+		assertThrows(IllegalStateException.class, () -> FireboltProperties.of(properties));
+	}
+
+	private Properties properties(String envKey, String envValue, String host) {
 		Properties properties = new Properties();
 		if (envValue != null) {
 			properties.put(envKey, envValue);
@@ -172,8 +195,7 @@ void hostAndEnvironment(String envKey, String envValue, String host, String expe
 		if (host != null) {
 			properties.put("host", host);
 		}
-		assertEquals(expectedHost, FireboltProperties.of(properties).getHost());
-		assertEquals(expectedEnvironment, FireboltProperties.of(properties).getEnvironment());
+		return properties;
 	}
 
 }
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
index 412ee2daa..6bca42345 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
@@ -5,13 +5,19 @@
 import com.firebolt.jdbc.exception.FireboltException;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -46,50 +52,43 @@ void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromNullHost() {
 	@Test
 	void shouldGetDefaultEngineWhenEngineNameIsNotProvided() throws SQLException {
 		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mock(ResultSet.class);
-		when(resultSet.next()).thenReturn(true);
-		when(resultSet.getString("status")).thenReturn("running");
-		when(resultSet.getString("url")).thenReturn("https://url");
-		when(resultSet.getString("engine_name")).thenReturn("hello-engine");
+		ResultSet resultSet = mockedResultSet(Map.of("status", "running", "url", "https://url", "engine_name", "hello-engine"));
 		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
 		when(statement.executeQuery()).thenReturn(resultSet);
 		assertEquals(Engine.builder().endpoint("https://url").name("hello-engine").build(),
 				fireboltEngineService.getEngine(null, "db"));
 	}
 
-	@Test
-	void shouldThrowExceptionWhenDefaultEngineNotRunning() throws SQLException {
-		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mock(ResultSet.class);
-		when(resultSet.next()).thenReturn(true);
-		when(resultSet.getString("status")).thenReturn("down");
-		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
-		when(statement.executeQuery()).thenReturn(resultSet);
-		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(null, "db"));
-	}
-
 	@Test
 	void shouldGetEngineWhenEngineNameIsProvided() throws SQLException {
 		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mock(ResultSet.class);
-		when(resultSet.next()).thenReturn(true);
-		when(resultSet.getString("status")).thenReturn("running");
-		when(resultSet.getString("url")).thenReturn("https://url");
+		ResultSet resultSet = mockedResultSet(Map.of("status", "running", "url", "https://url"));
 		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
 		when(statement.executeQuery()).thenReturn(resultSet);
 		assertEquals(Engine.builder().endpoint("https://url").name("some-engine").build(),
 				fireboltEngineService.getEngine("some-engine", "db"));
 	}
 
-	@Test
-	void shouldThrowExceptionWhenEngineNotRunning() throws SQLException {
+	@ParameterizedTest
+	@CsvSource(value = {
+			"down;some-engine;db;SELECT url, status",
+			"down;;db;SELECT.+JOIN",
+			"failed;'';db;SELECT.+JOIN",
+	}, delimiter = ';')
+	void shouldThrowExceptionWhenEngineNotRunning(String status, String engineName, String db, String queryRegex) throws SQLException {
 		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mock(ResultSet.class);
-		when(resultSet.next()).thenReturn(true);
-		when(resultSet.getString("status")).thenReturn("down");
-		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
+		ResultSet resultSet = mockedResultSet(Map.of("status", status));
+		when(fireboltConnection.prepareStatement(Mockito.matches(Pattern.compile(queryRegex, Pattern.MULTILINE | Pattern.DOTALL)))).thenReturn(statement);
 		when(statement.executeQuery()).thenReturn(resultSet);
-		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine("some-engine", "db"));
+		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(engineName, db));
 	}
 
+	private ResultSet mockedResultSet(Map<String, String> values) throws SQLException {
+		ResultSet resultSet = mock(ResultSet.class);
+		when(resultSet.next()).thenReturn(true);
+		for (Entry<String, String> column : values.entrySet()) {
+			when(resultSet.getString(column.getKey())).thenReturn(column.getValue());
+		}
+		return resultSet;
+	}
 }

From 675f8d062ee31e9922e359c3318dfa9a45ce199b Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Mon, 10 Jul 2023 19:32:50 +0300
Subject: [PATCH 08/15] applied PR comments

---
 .../com/firebolt/jdbc/client/query/StatementClientImpl.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index 83a8ac740..1f7b08805 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -205,7 +205,7 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 		getResponseFormatParameter(statementInfoWrapper.getType() == StatementType.QUERY, isLocalDb)
 				.ifPresent(format -> params.put(format.getLeft(), format.getRight()));
 		if (systemEngine) {
-			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId()); // "01h11x0zmecanh1vp2q1mar5nh"
+			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId());
 		} else {
 			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
 			params.put(FireboltQueryParameterKey.QUERY_ID.getKey(), statementInfoWrapper.getId());

From 2aee7a2dbadb29da3f9450301f1b7a7c1825dd2f Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Tue, 11 Jul 2023 14:46:37 +0300
Subject: [PATCH 09/15] applied some pr comments; TimeoutTest fails

---
 .../integration/tests/NumericTypesTest.java   |  2 +-
 .../integration/tests/SystemEngineTest.java   |  9 ++--
 .../client/query/StatementClientImpl.java     | 26 +++++++----
 .../jdbc/connection/FireboltConnection.java   | 13 ++----
 .../settings/FireboltProperties.java          |  9 +---
 .../connection/FireboltConnectionTest.java    |  8 ++--
 .../settings/FireboltPropertiesTest.java      | 46 ++++---------------
 7 files changed, 41 insertions(+), 72 deletions(-)

diff --git a/src/integrationTest/java/integration/tests/NumericTypesTest.java b/src/integrationTest/java/integration/tests/NumericTypesTest.java
index c0c2dda5b..5badb28b6 100644
--- a/src/integrationTest/java/integration/tests/NumericTypesTest.java
+++ b/src/integrationTest/java/integration/tests/NumericTypesTest.java
@@ -13,7 +13,7 @@
 public class NumericTypesTest extends IntegrationTest {
     @Test
     void shouldHaveCorrectInfo() throws SQLException {
-        try (Connection connection = this.createConnection("system");
+        try (Connection connection = this.createConnection(null);
              Statement statement = connection.createStatement();
              ResultSet resultSet = statement.executeQuery("SELECT 3::decimal")) {
             resultSet.next();
diff --git a/src/integrationTest/java/integration/tests/SystemEngineTest.java b/src/integrationTest/java/integration/tests/SystemEngineTest.java
index cd596d09d..eb348e22e 100644
--- a/src/integrationTest/java/integration/tests/SystemEngineTest.java
+++ b/src/integrationTest/java/integration/tests/SystemEngineTest.java
@@ -18,12 +18,11 @@ public class SystemEngineTest extends IntegrationTest {
 	private static final String DATABASE_NAME = "jdbc_system_engine_integration_test";
 	private static final String ENGINE_NAME = "jdbc_system_engine_integration_test_engine";
 	private static final String ENGINE_NEW_NAME = "jdbc_system_engine_integration_test_engine_2";
-	private static final String SYSTEM_ENGINE_NAME = "system";
 
 	@BeforeAll
 	void beforeAll() {
 		try {
-			executeStatementFromFile("/statements/system/ddl.sql", SYSTEM_ENGINE_NAME);
+			executeStatementFromFile("/statements/system/ddl.sql", null);
 		} catch (Exception e) {
 			log.warn("Could not execute statement", e);
 		}
@@ -32,15 +31,15 @@ void beforeAll() {
 	@AfterAll
 	void afterAll() {
 		try {
-			executeStatementFromFile("/statements/system/cleanup.sql", SYSTEM_ENGINE_NAME);
+			executeStatementFromFile("/statements/system/cleanup.sql", null);
 		} catch (Exception e) {
 			log.warn("Could not execute statement", e);
 		}
 	}
 
 	@Test
-	void shouldExecuteQueriesUsingSystemEngine() throws SQLException {
-		try (Connection connection = this.createConnection(SYSTEM_ENGINE_NAME)) {
+	void shouldExecuteEngineManagementQueries() throws SQLException {
+		try (Connection connection = this.createConnection(null)) {
 			List<String> queries = Arrays.asList(String.format("CREATE DATABASE IF NOT EXISTS %s", DATABASE_NAME),
 					String.format("CREATE ENGINE %s", ENGINE_NAME),
 					String.format("ATTACH ENGINE %s TO %s;", ENGINE_NAME, DATABASE_NAME),
diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index 1f7b08805..cbcec6eb3 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -207,17 +207,27 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 		if (systemEngine) {
 			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId());
 		} else {
-			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
+//			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
 			params.put(FireboltQueryParameterKey.QUERY_ID.getKey(), statementInfoWrapper.getId());
 			params.put(FireboltQueryParameterKey.COMPRESS.getKey(), fireboltProperties.isCompress() ? "1" : "0");
+//
+//			if (queryTimeout > -1) {
+//				params.put("max_execution_time", String.valueOf(queryTimeout));
+//			}
+//			if (maxRows > 0) {
+//				params.put("max_result_rows", String.valueOf(maxRows));
+//				params.put("result_overflow_mode", "break");
+//			}
+		}
 
-			if (queryTimeout > -1) {
-				params.put("max_execution_time", String.valueOf(queryTimeout));
-			}
-			if (maxRows > 0) {
-				params.put("max_result_rows", String.valueOf(maxRows));
-				params.put("result_overflow_mode", "break");
-			}
+		params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
+
+		if (queryTimeout > -1) {
+			params.put("max_execution_time", String.valueOf(queryTimeout));
+		}
+		if (maxRows > 0) {
+			params.put("max_result_rows", String.valueOf(maxRows));
+			params.put("resulresult_overflow_modet_overflow_mode", "break");
 		}
 
 		return params;
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index a7c7c56e8..722f2c3fe 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -33,7 +33,6 @@
 import java.util.*;
 import java.util.concurrent.Executor;
 
-import static com.firebolt.jdbc.connection.settings.FireboltProperties.SYSTEM_ENGINE_NAME;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
 
 @CustomLog
@@ -50,7 +49,6 @@ public class FireboltConnection implements Connection {
 	private final boolean systemEngine;
 	private boolean closed = true;
 	private FireboltProperties sessionProperties;
-	private FireboltProperties internalSystemEngineProperties;
 	private int networkTimeout;
 
 	//Properties that are used at the beginning of the connection for authentication
@@ -116,18 +114,18 @@ private void connect() throws FireboltException {
 		String accessToken = this.getAccessToken(loginProperties).orElse(StringUtils.EMPTY);
 		closed = false;
 		if (!PropertyUtil.isLocalDb(loginProperties)) {
-			internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, loginProperties.getAccount());
+			FireboltProperties internalSystemEngineProperties = createInternalSystemEngineProperties(accessToken, loginProperties.getAccount());
 			String accountId = fireboltAccountIdService.getValue(accessToken, loginProperties.getAccount());
-			if (!loginProperties.isSystemEngine()) {
+			if (systemEngine) {
+				//When using system engine, the system engine properties are the same as the session properties
+				sessionProperties = internalSystemEngineProperties.toBuilder().accountId(accountId).build();
+			} else {
 				sessionProperties = internalSystemEngineProperties.toBuilder()
 						.engine(loginProperties.getEngine())
 						.systemEngine(true)
 						.accountId(accountId)
 						.build();
 				sessionProperties = getSessionPropertiesForNonSystemEngine();
-			} else {
-				//When using system engine, the system engine properties are the same as the session properties
-				sessionProperties = internalSystemEngineProperties.toBuilder().accountId(accountId).build();
 			}
 		} else {
 			//When running packdb locally, the login properties are the session properties
@@ -146,7 +144,6 @@ private FireboltProperties createInternalSystemEngineProperties(String accessTok
 		return this.loginProperties
 				.toBuilder()
 				.systemEngine(true)
-				.engine(SYSTEM_ENGINE_NAME)
 				.compress(false)
 				.host(UrlUtil.createUrl(systemEngineEndpoint).getHost()).database(null).build();
 	}
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index b79e4eeab..f13bc33fd 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -21,7 +21,6 @@
 @CustomLog
 public class FireboltProperties {
 
-	public static final String SYSTEM_ENGINE_NAME = "system";
 	private static final Pattern DB_PATH_PATTERN = Pattern.compile("([a-zA-Z0-9_*\\-]+)");
 	private static final int FIREBOLT_SSL_PROXY_PORT = 443;
 	private static final int FIREBOLT_NO_SSL_PROXY_PORT = 9090;
@@ -115,11 +114,7 @@ public static FireboltProperties of(Properties... properties) {
 
 	private static String getEngine(Properties mergedProperties, String database) {
 		String engine = getSetting(mergedProperties, FireboltSessionProperty.ENGINE);
-		if (StringUtils.isEmpty(engine) && StringUtils.isEmpty(database)) {
-			return SYSTEM_ENGINE_NAME;
-		} else {
-			return engine;
-		}
+		return StringUtils.isEmpty(engine) && StringUtils.isEmpty(database) ? null : engine;
 	}
 
 	private static String getHost(String environment, Properties properties ) {
@@ -241,7 +236,7 @@ public static FireboltProperties copy(FireboltProperties properties) {
 	}
 
 	private static boolean isSystemEngine(String engine) {
-		return StringUtils.equalsIgnoreCase(SYSTEM_ENGINE_NAME, engine);
+		return engine == null;
 	}
 
 	public void addProperty(@NonNull String key, String value) {
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index 737aed831..014f7626e 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -22,8 +22,7 @@
 
 import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.*;
 import static org.mockito.Mockito.*;
 
 @ExtendWith(MockitoExtension.class)
@@ -399,12 +398,11 @@ void shouldGetEngineUrlWhenEngineIsProvided() throws SQLException {
 
 	@Test
 	void shouldNotGetEngineUrlOrDefaultEngineUrlWhenUsingSystemEngine() throws SQLException {
-		connectionProperties.put("engine", "system");
 		connectionProperties.put("database", "my_db");
 		when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://my_endpoint");
 
 		try (FireboltConnection connection = createConnection(URL, connectionProperties)) {
-			verify(fireboltEngineService, times(0)).getEngine(eq("system"), eq("my_db"));
+			verify(fireboltEngineService, times(0)).getEngine(isNull(), eq("my_db"));
 			assertEquals("my_endpoint", connection.getSessionProperties().getHost());
 		}
 	}
@@ -415,7 +413,7 @@ void noEngineAndDb() throws SQLException {
 
 		try (FireboltConnection connection = createConnection("jdbc:firebolt:?env=dev", connectionProperties)) {
 			assertEquals("my_endpoint", connection.getSessionProperties().getHost());
-			assertEquals("system", connection.getSessionProperties().getEngine());
+			assertNull(connection.getSessionProperties().getEngine());
 			assertTrue(connection.getSessionProperties().isSystemEngine());
 		}
 	}
diff --git a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
index eefa17ef9..d29d53b80 100644
--- a/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/settings/FireboltPropertiesTest.java
@@ -1,5 +1,6 @@
 package com.firebolt.jdbc.connection.settings;
 
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.CsvSource;
@@ -14,7 +15,7 @@ class FireboltPropertiesTest {
 
 	@Test
 	void shouldHaveDefaultPropertiesWhenOnlyTheRequiredFieldsAreSpecified() {
-		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().database("db").bufferSize(65536)
+		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().engine("engine").database("db").bufferSize(65536)
 				.sslCertificatePath("").sslMode("strict").path("").port(443) // 443 by default as SSL is enabled by
 				.systemEngine(false).compress(true)													// default
 				.principal(null).secret(null).host("host").ssl(true).additionalProperties(new HashMap<>())
@@ -23,6 +24,7 @@ void shouldHaveDefaultPropertiesWhenOnlyTheRequiredFieldsAreSpecified() {
 				.tcpKeepCount(10).account("firebolt").build();
 
 		Properties properties = new Properties();
+		properties.put("engine", "engine");
 		properties.put("host", "host");
 		properties.put("database", "db");
 		assertEquals(expectedDefaultProperties, FireboltProperties.of(properties));
@@ -31,6 +33,7 @@ void shouldHaveDefaultPropertiesWhenOnlyTheRequiredFieldsAreSpecified() {
 	@Test
 	void shouldHaveAllTheSpecifiedCustomProperties() {
 		Properties properties = new Properties();
+		properties.put("engine", "my_test");
 		properties.put("buffer_size", "51");
 		properties.put("socket_timeout_millis", "20");
 		properties.put("ssl", "1");
@@ -45,7 +48,7 @@ void shouldHaveAllTheSpecifiedCustomProperties() {
 		Map<String, String> customProperties = new HashMap<>();
 		customProperties.put("someCustomProperties", "custom_value");
 
-		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().bufferSize(51)
+		FireboltProperties expectedDefaultProperties = FireboltProperties.builder().engine("my_test").bufferSize(51)
 				.sslCertificatePath("root_cert").sslMode("none").path("example").database("myDb").compress(true)
 				.port(443).principal(null).secret(null).host("myDummyHost").ssl(true).systemEngine(false)
 				.additionalProperties(customProperties).account(null).keepAliveTimeoutMillis(300000)
@@ -101,43 +104,10 @@ void shouldUseCustomPortWhenProvided() {
 	void shouldUseSystemEngineWhenNoDbOrEngineProvided() {
 		Properties properties = new Properties();
 		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
-		assertTrue(FireboltProperties.of(properties).isSystemEngine());
-		assertEquals("system", fireboltProperties.getEngine());
-		assertNull(fireboltProperties.getDatabase());
-		assertFalse(fireboltProperties.isCompress());
-	}
-
-	@Test
-	void shouldNotUseSystemEngineWhenDbAsPathIsProvided() {
-		Properties properties = new Properties();
-		properties.put("path", "example");
-		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
-		assertFalse(FireboltProperties.of(properties).isSystemEngine());
-		assertNull(fireboltProperties.getEngine());
-		assertEquals("example", fireboltProperties.getDatabase());
-		assertTrue(fireboltProperties.isCompress());
-	}
-
-	@Test
-	void shouldNotUseSystemEngineWhenDbAsQueryParamIsProvided() {
-		Properties properties = new Properties();
-		properties.put("database", "example");
-		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
-		assertFalse(FireboltProperties.of(properties).isSystemEngine());
+		assertTrue(fireboltProperties.isSystemEngine());
 		assertNull(fireboltProperties.getEngine());
-		assertEquals("example", fireboltProperties.getDatabase());
-		assertTrue(fireboltProperties.isCompress());
-	}
-
-	@Test
-	void shouldNotUseSystemEngineWhenEngineIsProvided() {
-		Properties properties = new Properties();
-		properties.put("engine", "example");
-		FireboltProperties fireboltProperties = FireboltProperties.of(properties);
-		assertFalse(FireboltProperties.of(properties).isSystemEngine());
 		assertNull(fireboltProperties.getDatabase());
-		assertEquals("example", fireboltProperties.getEngine());
-		assertTrue(fireboltProperties.isCompress());
+		assertFalse(fireboltProperties.isCompress());
 	}
 
 	@Test
@@ -156,7 +126,7 @@ void shouldSupportUserClientsAndDrivers() {
 
 	@Test
 	void noEngineNoDbSystemEngine() {
-		assertEquals("system", FireboltProperties.of(new Properties()).getEngine());
+		assertNull(FireboltProperties.of(new Properties()).getEngine());
 	}
 
 	@ParameterizedTest

From b254840e50171991ffebf2ea6608dd9755626277 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Wed, 12 Jul 2023 11:37:08 +0300
Subject: [PATCH 10/15] completely removed "system" for system engine

---
 .../java/integration/ConnectionInfo.java      | 44 +++++++++++++--
 .../java/integration/IntegrationTest.java     | 35 +++++-------
 .../client/query/StatementClientImpl.java     | 11 +---
 .../settings/FireboltProperties.java          |  7 +--
 .../client/query/StatementClientImplTest.java | 55 ++++++++-----------
 .../connection/FireboltConnectionTest.java    | 16 +-----
 6 files changed, 81 insertions(+), 87 deletions(-)

diff --git a/src/integrationTest/java/integration/ConnectionInfo.java b/src/integrationTest/java/integration/ConnectionInfo.java
index 5e88373b5..8ce560933 100644
--- a/src/integrationTest/java/integration/ConnectionInfo.java
+++ b/src/integrationTest/java/integration/ConnectionInfo.java
@@ -1,10 +1,15 @@
 package integration;
 
+import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Stream;
 
+import static java.lang.String.format;
 import static java.lang.System.getProperty;
+import static java.util.stream.Collectors.joining;
 
 public class ConnectionInfo {
+	private static final String JDBC_URL_PREFIX = "jdbc:firebolt:";
 	private static volatile ConnectionInfo INSTANCE;
 	// principal and secret are used here instead of client_id and client_secret respectively as more common term also used in java security API.
 	private final String principal;
@@ -15,12 +20,23 @@ public class ConnectionInfo {
 	private final String engine;
 
 	private ConnectionInfo() {
-		principal = Optional.ofNullable(getProperty("client_id", getProperty("user"))).map(u -> u.replace("\"", "")).orElse(null);
-		secret = Optional.ofNullable(getProperty("client_secret", getProperty("password"))).map(p -> p.replace("\"", "")).orElse(null);
-		env = getProperty("env");
-		database = getProperty("db");
-		account = getProperty("account");
-		engine = getProperty("engine");
+		this(
+				getTrimmedProperty("client_id", "user"),
+				getTrimmedProperty("client_secret", "password"),
+				getProperty("env"),
+				getProperty("db"),
+				getProperty("account"),
+				getProperty("engine")
+		);
+	}
+
+	public ConnectionInfo(String principal, String secret, String env, String database, String account, String engine) {
+		this.principal = principal;
+		this.secret = secret;
+		this.env = env;
+		this.database = database;
+		this.account = account;
+		this.engine = engine;
 	}
 
 	public static ConnectionInfo getInstance() {
@@ -34,6 +50,10 @@ public static ConnectionInfo getInstance() {
 		return INSTANCE;
 	}
 
+	private static String getTrimmedProperty(String name, String alias) {
+		return Optional.ofNullable(getProperty(name, getProperty(alias))).map(u -> u.replace("\"", "")).orElse(null);
+	}
+
 	public String getPrincipal() {
 		return principal;
 	}
@@ -57,4 +77,16 @@ public String getAccount() {
 	public String getEngine() {
 		return engine;
 	}
+
+	public String toJdbcUrl() {
+		String params = Stream.of(param("env", env), param("engine", engine), param("account", account)).filter(Objects::nonNull).collect(joining("&"));
+		if (!params.isEmpty()) {
+			params = "?" + params;
+		}
+		return JDBC_URL_PREFIX + database + params;
+	}
+
+	private String param(String name, String value) {
+		return value == null ? null : format("%s=%s", name, value);
+	}
 }
diff --git a/src/integrationTest/java/integration/IntegrationTest.java b/src/integrationTest/java/integration/IntegrationTest.java
index a66eba9d4..c8628f6b3 100644
--- a/src/integrationTest/java/integration/IntegrationTest.java
+++ b/src/integrationTest/java/integration/IntegrationTest.java
@@ -1,20 +1,20 @@
 package integration;
 
+import com.firebolt.jdbc.client.HttpClientConfig;
+import com.google.common.io.Resources;
+import lombok.CustomLog;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.TestInstance;
+
 import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.Optional;
-
-import org.junit.jupiter.api.TestInstance;
-
-import com.firebolt.jdbc.client.HttpClientConfig;
-import com.google.common.io.Resources;
+import java.util.Objects;
 
-import lombok.CustomLog;
-import lombok.SneakyThrows;
+import static java.util.Objects.requireNonNull;
 
 @CustomLog
 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
@@ -31,18 +31,16 @@ protected Connection createLocalConnection(String queryParams) throws SQLExcepti
 	}
 
 	protected Connection createConnection() throws SQLException {
-		return DriverManager.getConnection(
-				JDBC_URL_PREFIX
-						+ integration.ConnectionInfo.getInstance().getDatabase() + "?" + getEnvParam() + getAccountParam() ,
+		return DriverManager.getConnection(integration.ConnectionInfo.getInstance().toJdbcUrl(),
 				integration.ConnectionInfo.getInstance().getPrincipal(),
 				integration.ConnectionInfo.getInstance().getSecret());
 	}
 
 	protected Connection createConnection(String engine) throws SQLException {
-		return DriverManager.getConnection(
-				JDBC_URL_PREFIX +
-						 integration.ConnectionInfo.getInstance().getDatabase()
-						+ Optional.ofNullable(engine).map(e -> "?" + getEnvParam() +"&engine=" + e + getAccountParam() ).orElse("?" + getEnvParam() + getAccountParam()),
+		ConnectionInfo current = integration.ConnectionInfo.getInstance();
+		ConnectionInfo updated = new ConnectionInfo(current.getPrincipal(), current.getSecret(),
+				current.getEnv(), current.getDatabase(), current.getAccount(), engine);
+		return DriverManager.getConnection(updated.toJdbcUrl(),
 				integration.ConnectionInfo.getInstance().getPrincipal(),
 				integration.ConnectionInfo.getInstance().getSecret());
 	}
@@ -61,7 +59,7 @@ protected void executeStatementFromFile(String path) {
 	@SneakyThrows
 	protected void executeStatementFromFile(String path, String engine) {
 		try (Connection connection = createConnection(engine); Statement statement = connection.createStatement()) {
-			String sql = Resources.toString(IntegrationTest.class.getResource(path), StandardCharsets.UTF_8);
+			String sql = Resources.toString(requireNonNull(IntegrationTest.class.getResource(path)), StandardCharsets.UTF_8);
 			statement.execute(sql);
 		}
 	}
@@ -75,9 +73,4 @@ protected void removeExistingClient() throws NoSuchFieldException, IllegalAccess
 	private String getAccountParam() {
 		return "&account=" + integration.ConnectionInfo.getInstance().getAccount();
 	}
-
-	private String getEnvParam() {
-		return "&env=" + integration.ConnectionInfo.getInstance().getEnv();
-	}
-
 }
diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index cbcec6eb3..af06cfc93 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -207,17 +207,8 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 		if (systemEngine) {
 			params.put(FireboltQueryParameterKey.ACCOUNT_ID.getKey(), fireboltProperties.getAccountId());
 		} else {
-//			params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
 			params.put(FireboltQueryParameterKey.QUERY_ID.getKey(), statementInfoWrapper.getId());
 			params.put(FireboltQueryParameterKey.COMPRESS.getKey(), fireboltProperties.isCompress() ? "1" : "0");
-//
-//			if (queryTimeout > -1) {
-//				params.put("max_execution_time", String.valueOf(queryTimeout));
-//			}
-//			if (maxRows > 0) {
-//				params.put("max_result_rows", String.valueOf(maxRows));
-//				params.put("result_overflow_mode", "break");
-//			}
 		}
 
 		params.put(FireboltQueryParameterKey.DATABASE.getKey(), fireboltProperties.getDatabase());
@@ -227,7 +218,7 @@ private Map<String, String> getAllParameters(FireboltProperties fireboltProperti
 		}
 		if (maxRows > 0) {
 			params.put("max_result_rows", String.valueOf(maxRows));
-			params.put("resulresult_overflow_modet_overflow_mode", "break");
+			params.put("result_overflow_mode", "break");
 		}
 
 		return params;
diff --git a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
index f13bc33fd..16535e3bd 100644
--- a/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
+++ b/src/main/java/com/firebolt/jdbc/connection/settings/FireboltProperties.java
@@ -74,7 +74,7 @@ public static FireboltProperties of(Properties... properties) {
 		String secret = getSetting(mergedProperties, FireboltSessionProperty.CLIENT_SECRET);
 		String path = getSetting(mergedProperties, FireboltSessionProperty.PATH);
 		String database = getDatabase(mergedProperties, path);
-		String engine = getEngine(mergedProperties, database);
+		String engine = getEngine(mergedProperties);
 		boolean isSystemEngine = isSystemEngine(engine);
 		boolean compress = ((Boolean) getSetting(mergedProperties, FireboltSessionProperty.COMPRESS))
 				&& !isSystemEngine;
@@ -112,9 +112,8 @@ public static FireboltProperties of(Properties... properties) {
 				.build();
 	}
 
-	private static String getEngine(Properties mergedProperties, String database) {
-		String engine = getSetting(mergedProperties, FireboltSessionProperty.ENGINE);
-		return StringUtils.isEmpty(engine) && StringUtils.isEmpty(database) ? null : engine;
+	private static String getEngine(Properties mergedProperties) {
+		return getSetting(mergedProperties, FireboltSessionProperty.ENGINE);
 	}
 
 	private static String getHost(String environment, Properties properties ) {
diff --git a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
index 3fba163c9..f9f12943d 100644
--- a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
@@ -10,7 +10,6 @@
 import lombok.NonNull;
 import okhttp3.*;
 import okio.Buffer;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.ArgumentCaptor;
@@ -19,13 +18,14 @@
 import org.mockito.junit.jupiter.MockitoExtension;
 
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 
 import static com.firebolt.jdbc.client.UserAgentFormatter.userAgent;
+import static java.lang.String.format;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.any;
@@ -42,20 +42,35 @@ class StatementClientImplTest {
 	private FireboltConnection connection;
 
 	@Test
-	@Disabled("Disabled until engine_url is available")
 	void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
+		Entry<String, String> result = shouldPostSqlQueryForSystemEngine(false);
+		String requestId = result.getKey();
+		String url = result.getValue();
+		assertEquals(
+				format("http://firebolt1:555/?result_overflow_mode=break&database=db1&output_format=TabSeparatedWithNamesAndTypes&query_id=%s&compress=1&max_result_rows=1&max_execution_time=15", requestId),
+				url);
+	}
+
+	@Test
+	void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException {
+		String url = shouldPostSqlQueryForSystemEngine(true).getValue();
+		assertEquals(
+				"http://firebolt1:555/dynamic/query?result_overflow_mode=break&database=db1&account_id=12345&output_format=TabSeparatedWithNamesAndTypes&max_result_rows=1&max_execution_time=15",
+				url);
+	}
+
+	private Entry<String, String> shouldPostSqlQueryForSystemEngine(boolean systemEngine) throws FireboltException, IOException {
 		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db1").compress(true)
-				.host("firebolt1").port(555).build();
+				.host("firebolt1").port(555).accountId("12345").systemEngine(systemEngine).build();
 		when(connection.getAccessToken())
 				.thenReturn(Optional.of("token"));
-
-		injectMockedResponse(okHttpClient, 200);
 		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
 				"ConnA:1.0.9", "ConnB:2.0.9");
+		injectMockedResponse(okHttpClient, 200);
 		Call call = getMockedCallWithResponse(200);
 		when(okHttpClient.newCall(any())).thenReturn(call);
 		StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("show databases").get(0);
-		statementClient.executeSqlStatement(statementInfoWrapper, fireboltProperties, false, 15, 1, true);
+		statementClient.executeSqlStatement(statementInfoWrapper, fireboltProperties, fireboltProperties.isSystemEngine(), 15, 1, true);
 
 		verify(okHttpClient).newCall(requestArgumentCaptor.capture());
 		Request actualRequest = requestArgumentCaptor.getValue();
@@ -65,33 +80,9 @@ void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 		expectedHeaders.put("User-Agent", userAgent("ConnB/2.0.9 JDBC/%s (Java %s; %s %s; ) ConnA/1.0.9"));
 
 		assertEquals(expectedHeaders, extractHeadersMap(actualRequest));
-		assertEquals("show databases;", actualQuery);
-		assertEquals(String.format(
-				"http://firebolt1:555/dynamic/query?result_overflow_mode=break&database=db1&output_format=TabSeparatedWithNamesAndTypes&query_id=1cfd2cc6-3a62-48e2-ac9c-83846d70f16a&compress=1&max_result_rows=1&max_execution_time=15",
-				statementInfoWrapper.getId()), actualRequest.url().toString());
-	}
-
-	@Test
-	void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException, URISyntaxException {
-		FireboltProperties fireboltProperties = FireboltProperties.builder().database("db1").compress(true)
-				.host("firebolt1").port(555).accountId("12345").build();
-		when(connection.getAccessToken())
-				.thenReturn(Optional.of("token"));
-		StatementClient statementClient = new StatementClientImpl(okHttpClient, mock(ObjectMapper.class), connection,
-				"ConnA:1.0.9", "ConnB:2.0.9");
-		injectMockedResponse(okHttpClient, 200);
-		Call call = getMockedCallWithResponse(200);
-		when(okHttpClient.newCall(any())).thenReturn(call);
-		StatementInfoWrapper statementInfoWrapper = StatementUtil.parseToStatementInfoWrappers("show databases").get(0);
-		statementClient.executeSqlStatement(statementInfoWrapper, fireboltProperties, true, 15, 1, true);
-
-		verify(okHttpClient).newCall(requestArgumentCaptor.capture());
-		Request actualRequest = requestArgumentCaptor.getValue();
-		String actualQuery = getActualRequestString(actualRequest);
 
 		assertEquals("show databases;", actualQuery);
-		assertEquals("http://firebolt1:555/?account_id=12345&output_format=TabSeparatedWithNamesAndTypes",
-				actualRequest.url().toString());
+		return Map.entry(statementInfoWrapper.getId(), actualRequest.url().toString());
 	}
 
 	@Test
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index 014f7626e..f225c9452 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -30,7 +30,7 @@ class FireboltConnectionTest {
 
 	private static final String URL = "jdbc:firebolt:db?env=dev&engine=eng";
 
-	private static final String SYSTEM_ENGINE_URL = "jdbc:firebolt:db?env=dev&engine=system";
+	private static final String SYSTEM_ENGINE_URL = "jdbc:firebolt:db?env=dev";
 
 	private static final String LOCAL_URL = "jdbc:firebolt:local_dev_db?ssl=false&max_query_size=10000000&use_standard_sql=1&mask_internal_errors=0&firebolt_enable_beta_functions=1&firebolt_case_insensitive_identifiers=1&rest_api_pull_timeout_sec=3600&rest_api_pull_interval_millisec=5000&rest_api_retry_times=10&host=localhost";
 	private final FireboltConnectionTokens fireboltConnectionTokens = FireboltConnectionTokens.builder().build();
@@ -375,17 +375,6 @@ void shouldThrowExceptionWhenPreparingStatementWIthInvalidResultSetType() throws
 		}
 	}
 
-	@Test
-	void shouldGetDefaultEngineWhenEngineIsNotProvided() throws SQLException {
-		connectionProperties.put("engine", "");
-		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().name("default_engine").endpoint("http://my-endpoint").build());
-		try (FireboltConnection  connection = createConnection(URL, connectionProperties)) {
-			verify(fireboltEngineService).getEngine("", "db");
-			assertEquals("default_engine", connection.getSessionProperties().getEngine());
-			assertEquals("http://my-endpoint", connection.getSessionProperties().getHost());
-		}
-	}
-
 	@Test
 	void shouldGetEngineUrlWhenEngineIsProvided() throws SQLException {
 		connectionProperties.put("engine", "engine");
@@ -401,7 +390,7 @@ void shouldNotGetEngineUrlOrDefaultEngineUrlWhenUsingSystemEngine() throws SQLEx
 		connectionProperties.put("database", "my_db");
 		when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://my_endpoint");
 
-		try (FireboltConnection connection = createConnection(URL, connectionProperties)) {
+		try (FireboltConnection connection = createConnection(SYSTEM_ENGINE_URL, connectionProperties)) {
 			verify(fireboltEngineService, times(0)).getEngine(isNull(), eq("my_db"));
 			assertEquals("my_endpoint", connection.getSessionProperties().getHost());
 		}
@@ -418,7 +407,6 @@ void noEngineAndDb() throws SQLException {
 		}
 	}
 
-
 	private FireboltConnection createConnection(String url, Properties props) throws FireboltException {
 		return new FireboltConnection(url, props, fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService, fireboltAccountIdService);
 	}

From af46d6613d763beb8040b707d31e736f8e435afd Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Wed, 12 Jul 2023 18:48:56 +0300
Subject: [PATCH 11/15] fixed discovery of engine and validation of database

---
 .../java/integration/IntegrationTest.java     |  1 -
 .../MockWebServerAwareIntegrationTest.java    | 33 ++++++++
 .../tests/client/RetryPolicyTest.java         | 44 +++-------
 .../integration/tests/client/TLSTest.java     | 36 ++-------
 .../tests/client/UsageTrackingTest.java       | 34 ++------
 .../com/firebolt/jdbc/connection/Engine.java  | 14 ++--
 .../jdbc/connection/FireboltConnection.java   | 22 +++--
 .../jdbc/service/FireboltEngineService.java   | 80 ++++++++-----------
 .../connection/FireboltConnectionTest.java    | 22 +++--
 .../service/FireboltEngineServiceTest.java    | 50 +++++++-----
 10 files changed, 157 insertions(+), 179 deletions(-)
 create mode 100644 src/integrationTest/java/integration/MockWebServerAwareIntegrationTest.java

diff --git a/src/integrationTest/java/integration/IntegrationTest.java b/src/integrationTest/java/integration/IntegrationTest.java
index c8628f6b3..6f27b45b6 100644
--- a/src/integrationTest/java/integration/IntegrationTest.java
+++ b/src/integrationTest/java/integration/IntegrationTest.java
@@ -12,7 +12,6 @@
 import java.sql.DriverManager;
 import java.sql.SQLException;
 import java.sql.Statement;
-import java.util.Objects;
 
 import static java.util.Objects.requireNonNull;
 
diff --git a/src/integrationTest/java/integration/MockWebServerAwareIntegrationTest.java b/src/integrationTest/java/integration/MockWebServerAwareIntegrationTest.java
new file mode 100644
index 000000000..9ddd2cf6c
--- /dev/null
+++ b/src/integrationTest/java/integration/MockWebServerAwareIntegrationTest.java
@@ -0,0 +1,33 @@
+package integration;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.io.IOException;
+
+import static java.lang.String.format;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public abstract class MockWebServerAwareIntegrationTest extends IntegrationTest {
+    protected MockWebServer mockBackEnd;
+    private final int INIT_STATEMENTS_COUNT = 1; // The statement that validates that DB exists.
+
+    @BeforeEach
+    void setUp() throws IOException {
+        mockBackEnd = new MockWebServer();
+        mockBackEnd.start();
+        mockBackEnd.enqueue(new MockResponse().setResponseCode(200).setBody(format("database_name%nstring%n%s", System.getProperty("db"))));
+    }
+
+    @AfterEach
+    void tearDown() throws IOException {
+        mockBackEnd.close();
+    }
+
+
+    protected void assertMockBackendRequestsCount(int expected) {
+        assertEquals(INIT_STATEMENTS_COUNT + expected, mockBackEnd.getRequestCount());
+    }
+}
diff --git a/src/integrationTest/java/integration/tests/client/RetryPolicyTest.java b/src/integrationTest/java/integration/tests/client/RetryPolicyTest.java
index 44705dd69..5fbfb298d 100644
--- a/src/integrationTest/java/integration/tests/client/RetryPolicyTest.java
+++ b/src/integrationTest/java/integration/tests/client/RetryPolicyTest.java
@@ -1,47 +1,29 @@
 package integration.tests.client;
 
-import static com.firebolt.jdbc.exception.ExceptionType.INVALID_REQUEST;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.IOException;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
 import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
-
-import integration.IntegrationTest;
+import integration.MockWebServerAwareIntegrationTest;
 import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
-
-public class RetryPolicyTest extends IntegrationTest {
-
-	private MockWebServer mockBackEnd;
+import org.junit.jupiter.api.Test;
 
-	@BeforeEach
-	void setUp() throws IOException {
-		mockBackEnd = new MockWebServer();
-		mockBackEnd.start();
-	}
+import java.sql.SQLException;
+import java.sql.Statement;
 
-	@AfterEach
-	void tearDown() throws IOException {
-		mockBackEnd.close();
-	}
+import static com.firebolt.jdbc.exception.ExceptionType.INVALID_REQUEST;
+import static java.lang.String.format;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
+public class RetryPolicyTest extends MockWebServerAwareIntegrationTest {
 	@Test
 	public void shouldThrowExceptionOn400WithoutRetry() throws SQLException {
 		mockBackEnd.enqueue(new MockResponse().setResponseCode(400));
 		try (FireboltConnection fireboltConnection = (FireboltConnection) createLocalConnection(
-				String.format("?ssl=0&port=%d&max_retries=%d", mockBackEnd.getPort(), 3));
+				format("?ssl=0&port=%d&max_retries=%d", mockBackEnd.getPort(), 3));
 				Statement statement = fireboltConnection.createStatement()) {
 			FireboltException ex = assertThrows(FireboltException.class, () -> statement.execute("SELECT 1;"));
 			assertEquals(ex.getType(), INVALID_REQUEST);
-			assertEquals(1, mockBackEnd.getRequestCount());
+			assertMockBackendRequestsCount(1);
 		}
 	}
 
@@ -51,10 +33,10 @@ public void shouldRetryOn502() throws SQLException {
 		mockBackEnd.enqueue(new MockResponse().setResponseCode(502));
 		mockBackEnd.enqueue(new MockResponse().setResponseCode(200));
 		try (FireboltConnection fireboltConnection = (FireboltConnection) createLocalConnection(
-				String.format("?ssl=0&port=%d&max_retries=%d", mockBackEnd.getPort(), 3));
+				format("?ssl=0&port=%d&max_retries=%d", mockBackEnd.getPort(), 3));
 				Statement statement = fireboltConnection.createStatement()) {
 			statement.execute("SELECT 1;");
-			assertEquals(3, mockBackEnd.getRequestCount());
+			assertMockBackendRequestsCount(3);
 		}
 	}
 
diff --git a/src/integrationTest/java/integration/tests/client/TLSTest.java b/src/integrationTest/java/integration/tests/client/TLSTest.java
index 58edfb268..78c9b6ccd 100644
--- a/src/integrationTest/java/integration/tests/client/TLSTest.java
+++ b/src/integrationTest/java/integration/tests/client/TLSTest.java
@@ -1,6 +1,11 @@
 package integration.tests.client;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import com.firebolt.jdbc.connection.FireboltConnection;
+import integration.MockWebServerAwareIntegrationTest;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.tls.HandshakeCertificates;
+import okhttp3.tls.HeldCertificate;
+import org.junit.jupiter.api.Test;
 
 import java.io.File;
 import java.io.FileWriter;
@@ -11,32 +16,7 @@
 import java.sql.Statement;
 import java.util.UUID;
 
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import com.firebolt.jdbc.connection.FireboltConnection;
-
-import integration.IntegrationTest;
-import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
-import okhttp3.tls.HandshakeCertificates;
-import okhttp3.tls.HeldCertificate;
-
-public class TLSTest extends IntegrationTest {
-	private MockWebServer mockBackEnd;
-
-	@BeforeEach
-	void setUp() throws IOException {
-		mockBackEnd = new MockWebServer();
-		mockBackEnd.start();
-	}
-
-	@AfterEach
-	void tearDown() throws IOException {
-		mockBackEnd.close();
-	}
-
+public class TLSTest extends MockWebServerAwareIntegrationTest {
 	@Test
 	public void shouldUseTLS() throws SQLException, IOException, NoSuchFieldException, IllegalAccessException {
 		mockBackEnd.enqueue(new MockResponse().setResponseCode(200));
@@ -70,7 +50,7 @@ public void shouldUseTLS() throws SQLException, IOException, NoSuchFieldExceptio
 				String.format("?ssl_certificate_path=%s&port=%s", path, mockBackEnd.getPort()));
 				Statement statement = fireboltConnection.createStatement()) {
 			statement.execute("SELECT 1;");
-			assertEquals(1, mockBackEnd.getRequestCount());
+			assertMockBackendRequestsCount(1);
 		} finally {
 			removeExistingClient();
 		}
diff --git a/src/integrationTest/java/integration/tests/client/UsageTrackingTest.java b/src/integrationTest/java/integration/tests/client/UsageTrackingTest.java
index a11e79ba1..850e3c5d7 100644
--- a/src/integrationTest/java/integration/tests/client/UsageTrackingTest.java
+++ b/src/integrationTest/java/integration/tests/client/UsageTrackingTest.java
@@ -1,39 +1,19 @@
 package integration.tests.client;
 
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.io.IOException;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import org.apache.commons.lang3.StringUtils;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
 import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.util.VersionUtil;
-
-import integration.IntegrationTest;
+import integration.MockWebServerAwareIntegrationTest;
 import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
 import okhttp3.mockwebserver.RecordedRequest;
+import org.apache.commons.lang3.StringUtils;
+import org.junit.jupiter.api.Test;
 
-public class UsageTrackingTest extends IntegrationTest {
-
-	private MockWebServer mockBackEnd;
-
-	@BeforeEach
-	void setUp() throws IOException {
-		mockBackEnd = new MockWebServer();
-		mockBackEnd.start();
-	}
+import java.sql.SQLException;
+import java.sql.Statement;
 
-	@AfterEach
-	void tearDown() throws IOException {
-		mockBackEnd.close();
-	}
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
+public class UsageTrackingTest extends MockWebServerAwareIntegrationTest {
 	@Test
 	public void shouldSendRequestWithUserAgentHeaderContainingDriverAndClientInfo()
 			throws SQLException, InterruptedException {
diff --git a/src/main/java/com/firebolt/jdbc/connection/Engine.java b/src/main/java/com/firebolt/jdbc/connection/Engine.java
index d00040f5c..47f355b60 100644
--- a/src/main/java/com/firebolt/jdbc/connection/Engine.java
+++ b/src/main/java/com/firebolt/jdbc/connection/Engine.java
@@ -1,13 +1,13 @@
 package com.firebolt.jdbc.connection;
 
-import lombok.Builder;
-import lombok.Data;
+import lombok.*;
 
-@Builder
+@AllArgsConstructor
 @Data
+@EqualsAndHashCode
 public class Engine {
-	private String endpoint;
-	private String id;
-	private String status;
-	private String name;
+	private final String endpoint;
+	private final String status;
+	private final String name;
+	private final String database;
 }
diff --git a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
index 722f2c3fe..d731a2379 100644
--- a/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
+++ b/src/main/java/com/firebolt/jdbc/connection/FireboltConnection.java
@@ -33,6 +33,7 @@
 import java.util.*;
 import java.util.concurrent.Executor;
 
+import static java.lang.String.format;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
 
 @CustomLog
@@ -59,7 +60,7 @@ public FireboltConnection(@NonNull String url, Properties connectionSettings,
 							  FireboltGatewayUrlService fireboltGatewayUrlService,
 							  FireboltStatementService fireboltStatementService,
 							  FireboltEngineService fireboltEngineService,
-							  FireboltAccountIdService fireboltAccountIdService) throws FireboltException {
+							  FireboltAccountIdService fireboltAccountIdService) throws SQLException {
 		this.loginProperties = this.extractFireboltProperties(url, connectionSettings);
 
 		this.fireboltAuthenticationService = fireboltAuthenticationService;
@@ -78,7 +79,7 @@ public FireboltConnection(@NonNull String url, Properties connectionSettings,
 
 	// This code duplication between constructors is done because of back reference: dependent services require reference to current instance of FireboltConnection that prevents using constructor chaining or factory method.
 	@ExcludeFromJacocoGeneratedReport
-	public FireboltConnection(@NonNull String url, Properties connectionSettings) throws FireboltException {
+	public FireboltConnection(@NonNull String url, Properties connectionSettings) throws SQLException {
 		this.loginProperties = extractFireboltProperties(url, connectionSettings);
 		OkHttpClient httpClient = getHttpClient(loginProperties);
 		ObjectMapper objectMapper = FireboltObjectMapper.getInstance();
@@ -110,7 +111,7 @@ private <T> FireboltAccountRetriever<T> createFireboltAccountRetriever(OkHttpCli
 		return new FireboltAccountRetriever<>(httpClient, objectMapper, this, loginProperties.getUserDrivers(), loginProperties.getUserClients(), loginProperties.getHost(), path, type);
 	}
 
-	private void connect() throws FireboltException {
+	private void connect() throws SQLException {
 		String accessToken = this.getAccessToken(loginProperties).orElse(StringUtils.EMPTY);
 		closed = false;
 		if (!PropertyUtil.isLocalDb(loginProperties)) {
@@ -131,12 +132,20 @@ private void connect() throws FireboltException {
 			//When running packdb locally, the login properties are the session properties
 			sessionProperties = loginProperties;
 		}
+		assertDatabaseExisting(sessionProperties.getDatabase());
+
 		log.debug("Connection opened");
 	}
 
-	private FireboltProperties getSessionPropertiesForNonSystemEngine() throws FireboltException {
+	private FireboltProperties getSessionPropertiesForNonSystemEngine() throws SQLException {
 		Engine engine = fireboltEngineService.getEngine(loginProperties.getEngine(), loginProperties.getDatabase());
-		return loginProperties.toBuilder().host(engine.getEndpoint()).engine(engine.getName()).systemEngine(false).build();
+		return loginProperties.toBuilder().host(engine.getEndpoint()).engine(engine.getName()).systemEngine(false).database(engine.getDatabase()).build();
+	}
+
+	private void assertDatabaseExisting(String database) throws SQLException {
+		if (database !=  null && !fireboltEngineService.doesDatabaseExist(database)) {
+			throw new FireboltException(format("Database %s does not exist", database));
+		}
 	}
 
 	private FireboltProperties createInternalSystemEngineProperties(String accessToken, String account) throws FireboltException {
@@ -422,8 +431,7 @@ public synchronized void addProperty(Pair<String, String> property) throws Fireb
 		} catch (FireboltException e) {
 			throw e;
 		} catch (Exception e) {
-			throw new FireboltException(
-					String.format("Could not set property %s=%s", property.getLeft(), property.getRight()), e);
+			throw new FireboltException(format("Could not set property %s=%s", property.getLeft(), property.getRight()), e);
 		}
 	}
 
diff --git a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
index ee009cc9c..7b9e35837 100644
--- a/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
+++ b/src/main/java/com/firebolt/jdbc/service/FireboltEngineService.java
@@ -1,12 +1,10 @@
 package com.firebolt.jdbc.service;
 
-import com.firebolt.jdbc.CheckedFunction;
 import com.firebolt.jdbc.connection.Engine;
 import com.firebolt.jdbc.connection.FireboltConnection;
 import com.firebolt.jdbc.exception.FireboltException;
 import lombok.CustomLog;
 import lombok.RequiredArgsConstructor;
-import org.apache.commons.lang3.StringUtils;
 
 import javax.annotation.Nullable;
 import java.sql.PreparedStatement;
@@ -20,19 +18,16 @@
 @CustomLog
 public class FireboltEngineService {
     private static final String ENGINE_URL = "url";
-    private static final String ENGINE_NAME = "engine_name";
-    private static final String STATUS_FIELD_NAME = "status";
-    private static final String DEFAULT_ENGINE_QUERY = "SELECT engs.url, engs.status, engs.engine_name\n" +
-            "FROM information_schema.databases AS dbs\n" +
-            "INNER JOIN information_schema.engines AS engs\n" +
-            "ON engs.attached_to = dbs.database_name\n" +
-            "AND engs.engine_name = NULLIF(SPLIT_PART(ARRAY_FIRST(\n" +
-            "        eng_name -> eng_name LIKE '%%(default)',\n" +
-            "        SPLIT(',', attached_engines)\n" +
-            "    ), ' ', 1), '')\n" +
-            "WHERE database_name = ?";
-    private static final String ENGINE_QUERY = "SELECT url, status FROM information_schema.engines WHERE engine_name=?";
+    private static final String STATUS_FIELD = "status";
+    private static final String ENGINE_NAME_FIELD = "engine_name";
     private static final String RUNNING_STATUS = "running";
+    private static final String ENGINE_QUERY =
+            "SELECT engs.url, engs.attached_to, dbs.database_name, engs.status, engs.engine_name " +
+            "FROM information_schema.engines as engs " +
+            "LEFT JOIN information_schema.databases as dbs ON engs.attached_to = dbs.database_name " +
+            "WHERE engs.engine_name = ?";
+    private static final String DATABASE_QUERY = "SELECT database_name FROM information_schema.databases WHERE database_name=?";
+
     private final FireboltConnection fireboltConnection;
 
     /**
@@ -47,47 +42,42 @@ public String getEngineNameByHost(String engineHost) throws FireboltException {
                         format("Could not establish the engine from the host: %s", engineHost)));
     }
 
-    public Engine getEngine(@Nullable String name, @Nullable String database) throws FireboltException {
-        if (StringUtils.isEmpty(name)) {
-            return getDefaultEngine(database);
-        } else {
-            return Engine.builder().name(name).endpoint(getEngineEndpoint(name)).build();
+    public boolean doesDatabaseExist(String database) throws SQLException {
+        try (PreparedStatement ps = fireboltConnection.prepareStatement(DATABASE_QUERY)) {
+            ps.setString(1, database);
+            try (ResultSet rs = ps.executeQuery()) {
+                return rs.next();
+            }
         }
     }
 
-    private Engine getDefaultEngine(String database) throws FireboltException {
-        return getRowValue(DEFAULT_ENGINE_QUERY, database, rs -> Engine.builder().endpoint(rs.getString(ENGINE_URL)).name(rs.getString(ENGINE_NAME)).build(),
-                "The default engine for the database %s could not be found",
-                "The default engine for the database %s is not running. Status: %s",
-                "Could not get default engine url for database %s");
-    }
-
-    private String getEngineEndpoint(String engine) throws FireboltException {
-        return getRowValue(ENGINE_QUERY, engine, rs -> rs.getString(ENGINE_URL),
-                "The engine with the name %s could not be found",
-                "The engine with the name %s is not running. Status: %s",
-                "Could not get engine url for engine %s");
-    }
-
-    private <T> T getRowValue(String query, String queryArg, CheckedFunction<ResultSet, T> valueExtractor, String noDataMessage, String engineNotRunningMessage, String sqlFailureMessage) throws FireboltException {
-        try (PreparedStatement ps = fireboltConnection.prepareStatement(query)) {
-            ps.setString(1, queryArg);
+    public Engine getEngine(String engine, @Nullable String database) throws SQLException {
+        if (engine == null) {
+            throw new IllegalArgumentException("Cannot retrieve engine parameters because its name is null");
+        }
+        try (PreparedStatement ps = fireboltConnection.prepareStatement(ENGINE_QUERY)) {
+            ps.setString(1, engine);
             try (ResultSet rs = ps.executeQuery()) {
                 if (!rs.next()) {
-                    throw new FireboltException(format(noDataMessage, queryArg));
+                    throw new FireboltException(format("The engine with the name %s could not be found", engine));
+                }
+                String status = rs.getString(STATUS_FIELD);
+                if (!isEngineRunning(status)) {
+                    throw new FireboltException(format("The engine with the name %s is not running. Status: %s", engine, status));
+                }
+                String attachedDatabase = rs.getString("attached_to");
+                if (attachedDatabase == null) {
+                    throw new FireboltException(format("The engine with the name %s is not attached to any database", engine));
                 }
-                String status = rs.getString(STATUS_FIELD_NAME);
-                if (isEngineNotRunning(status)) {
-                    throw new FireboltException(format(engineNotRunningMessage, queryArg, status));
+                if (database != null && !database.equals(attachedDatabase)) {
+                    throw new FireboltException(format("The engine with the name %s is not attached to database %s", engine, database));
                 }
-                return valueExtractor.apply(rs);
+                return new Engine(rs.getString(ENGINE_URL), status, rs.getString(ENGINE_NAME_FIELD), attachedDatabase);
             }
-        } catch (SQLException e) {
-            throw new FireboltException(format(sqlFailureMessage, queryArg), e);
         }
     }
 
-    private boolean isEngineNotRunning(String status) {
-        return !RUNNING_STATUS.equalsIgnoreCase(status);
+    private boolean isEngineRunning(String status) {
+        return RUNNING_STATUS.equalsIgnoreCase(status);
     }
 }
diff --git a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
index f225c9452..898a8f47e 100644
--- a/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
+++ b/src/test/java/com/firebolt/jdbc/connection/FireboltConnectionTest.java
@@ -54,7 +54,7 @@ class FireboltConnectionTest {
 
 
 	@BeforeEach
-	void init() throws FireboltException {
+	void init() throws SQLException {
 		connectionProperties = new Properties();
 		connectionProperties.put("client_id", "somebody");
 		connectionProperties.put("client_secret", "pa$$word");
@@ -64,6 +64,7 @@ void init() throws FireboltException {
 		lenient().when(fireboltGatewayUrlService.getUrl(any(), any())).thenReturn("http://foo:8080/bar");
 		engine = new Engine("endpoint", "id123", "OK", "noname");
 		lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(engine);
+		lenient().when(fireboltEngineService.doesDatabaseExist(any())).thenReturn(true);
 	}
 
 	@Test
@@ -261,7 +262,7 @@ void shouldRemoveExpiredToken() throws SQLException {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			when(fireboltAuthenticationService.getConnectionTokens("http://host:8080", fireboltProperties))
 					.thenReturn(FireboltConnectionTokens.builder().build());
-			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://hello").build());
+			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(new Engine("http://hello", null, null, null));
 
 			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
 				fireboltConnection.removeExpiredTokens();
@@ -273,14 +274,12 @@ void shouldRemoveExpiredToken() throws SQLException {
 	@Test
 	void shouldReturnConnectionTokenWhenAvailable() throws SQLException {
 		String accessToken = "hello";
-		FireboltProperties fireboltProperties = FireboltProperties.builder().host("host").path("/db").port(8080)
-				.build();
+		FireboltProperties fireboltProperties = FireboltProperties.builder().host("host").path("/db").port(8080).build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			FireboltConnectionTokens connectionTokens = FireboltConnectionTokens.builder().accessToken(accessToken).build();
-			when(fireboltAuthenticationService.getConnectionTokens(eq("http://host:8080"), any()))
-					.thenReturn(connectionTokens);
-			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("https://engineHost").build());
+			when(fireboltAuthenticationService.getConnectionTokens(eq("http://host:8080"), any())).thenReturn(connectionTokens);
+			lenient().when(fireboltEngineService.getEngine(any(), any())).thenReturn(new Engine("http://engineHost", null, null, null));
 			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
 				verify(fireboltAuthenticationService).getConnectionTokens("http://host:8080", fireboltProperties);
 				assertEquals(accessToken, fireboltConnection.getAccessToken().get());
@@ -290,8 +289,7 @@ void shouldReturnConnectionTokenWhenAvailable() throws SQLException {
 
 	@Test
 	void shouldNotReturnConnectionTokenWithLocalDb() throws SQLException {
-		FireboltProperties fireboltProperties = FireboltProperties.builder().host("localhost").path("/db").port(8080)
-				.build();
+		FireboltProperties fireboltProperties = FireboltProperties.builder().host("localhost").path("/db").port(8080).build();
 		try (MockedStatic<FireboltProperties> mockedFireboltProperties = Mockito.mockStatic(FireboltProperties.class)) {
 			when(FireboltProperties.of(any())).thenReturn(fireboltProperties);
 			try (FireboltConnection fireboltConnection = createConnection(URL, connectionProperties)) {
@@ -354,7 +352,7 @@ void shouldThrowExceptionWhenCannotUnwrap() throws SQLException {
 	void shouldGetDatabaseWhenGettingCatalog() throws SQLException {
 		connectionProperties.put("database", "db");
 		try (Connection connection = createConnection(URL, connectionProperties)) {
-			assertEquals("db", connection.getCatalog());
+			assertEquals("noname", connection.getCatalog()); // retrieved engine's DB's name is "noname". Firebolt treats DB as catalog
 		}
 	}
 
@@ -378,7 +376,7 @@ void shouldThrowExceptionWhenPreparingStatementWIthInvalidResultSetType() throws
 	@Test
 	void shouldGetEngineUrlWhenEngineIsProvided() throws SQLException {
 		connectionProperties.put("engine", "engine");
-		when(fireboltEngineService.getEngine(any(), any())).thenReturn(Engine.builder().endpoint("http://my_endpoint").build());
+		when(fireboltEngineService.getEngine(any(), any())).thenReturn(new Engine("http://my_endpoint", null, null, null));
 		try (FireboltConnection connection = createConnection(URL, connectionProperties)) {
 			verify(fireboltEngineService).getEngine("engine", "db");
 			assertEquals("http://my_endpoint", connection.getSessionProperties().getHost());
@@ -407,7 +405,7 @@ void noEngineAndDb() throws SQLException {
 		}
 	}
 
-	private FireboltConnection createConnection(String url, Properties props) throws FireboltException {
+	private FireboltConnection createConnection(String url, Properties props) throws SQLException {
 		return new FireboltConnection(url, props, fireboltAuthenticationService, fireboltGatewayUrlService, fireboltStatementService, fireboltEngineService, fireboltAccountIdService);
 	}
 }
diff --git a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
index 6bca42345..4bf0cc15f 100644
--- a/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
+++ b/src/test/java/com/firebolt/jdbc/service/FireboltEngineServiceTest.java
@@ -15,6 +15,7 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.regex.Pattern;
@@ -22,8 +23,7 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 @ExtendWith(MockitoExtension.class)
 class FireboltEngineServiceTest {
@@ -51,43 +51,51 @@ void shouldThrowExceptionWhenThEngineCannotBeEstablishedFromNullHost() {
 
 	@Test
 	void shouldGetDefaultEngineWhenEngineNameIsNotProvided() throws SQLException {
-		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mockedResultSet(Map.of("status", "running", "url", "https://url", "engine_name", "hello-engine"));
-		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
-		when(statement.executeQuery()).thenReturn(resultSet);
-		assertEquals(Engine.builder().endpoint("https://url").name("hello-engine").build(),
-				fireboltEngineService.getEngine(null, "db"));
+		assertThrows(IllegalArgumentException.class, () -> fireboltEngineService.getEngine(null, "db"));
 	}
 
 	@Test
 	void shouldGetEngineWhenEngineNameIsProvided() throws SQLException {
 		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mockedResultSet(Map.of("status", "running", "url", "https://url"));
+		ResultSet resultSet = mockedResultSet(Map.of("status", "running", "url", "https://url", "attached_to", "db", "engine_name", "some-engine"));
 		when(fireboltConnection.prepareStatement(anyString())).thenReturn(statement);
 		when(statement.executeQuery()).thenReturn(resultSet);
-		assertEquals(Engine.builder().endpoint("https://url").name("some-engine").build(),
-				fireboltEngineService.getEngine("some-engine", "db"));
+		assertEquals(new Engine("https://url", "running", "some-engine", "db"), fireboltEngineService.getEngine("some-engine", "db"));
 	}
 
 	@ParameterizedTest
 	@CsvSource(value = {
-			"down;some-engine;db;SELECT url, status",
-			"down;;db;SELECT.+JOIN",
-			"failed;'';db;SELECT.+JOIN",
+			"engine1;db1;http://url1;running;;The engine with the name engine1 is not attached to any database",
+			"engine1;db1;http://url1;running;db2;The engine with the name engine1 is not attached to database db1",
+			"engine1;db1;http://url1;starting;;The engine with the name engine1 is not running. Status: starting",
+			"engine2;;;;;The engine with the name engine2 could not be found",
 	}, delimiter = ';')
-	void shouldThrowExceptionWhenEngineNotRunning(String status, String engineName, String db, String queryRegex) throws SQLException {
+	void shouldThrowExceptionWhenSomethingIsWrong(String engineName, String db, String endpoint, String status, String attachedDb, String errorMessage) throws SQLException {
 		PreparedStatement statement = mock(PreparedStatement.class);
-		ResultSet resultSet = mockedResultSet(Map.of("status", status));
-		when(fireboltConnection.prepareStatement(Mockito.matches(Pattern.compile(queryRegex, Pattern.MULTILINE | Pattern.DOTALL)))).thenReturn(statement);
+		Map<String, String> rsData = null;
+		if (endpoint != null || status != null || attachedDb != null) {
+			rsData = new HashMap<>();
+			rsData.put("url", endpoint);
+			rsData.put("status", status);
+			rsData.put("attached_to", attachedDb);
+			rsData.put("engine_name", engineName);
+		}
+		ResultSet resultSet = mockedResultSet(rsData);
+		when(fireboltConnection.prepareStatement(Mockito.matches(Pattern.compile("SELECT.+JOIN", Pattern.MULTILINE | Pattern.DOTALL)))).thenReturn(statement);
 		when(statement.executeQuery()).thenReturn(resultSet);
-		assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(engineName, db));
+		assertEquals(errorMessage, assertThrows(FireboltException.class, () -> fireboltEngineService.getEngine(engineName, db)).getMessage());
+		Mockito.verify(statement, Mockito.times(1)).setString(1, engineName);
 	}
 
 	private ResultSet mockedResultSet(Map<String, String> values) throws SQLException {
 		ResultSet resultSet = mock(ResultSet.class);
-		when(resultSet.next()).thenReturn(true);
-		for (Entry<String, String> column : values.entrySet()) {
-			when(resultSet.getString(column.getKey())).thenReturn(column.getValue());
+		if (values == null) {
+			when(resultSet.next()).thenReturn(false);
+		} else {
+			when(resultSet.next()).thenReturn(true, false);
+			for (Entry<String, String> column : values.entrySet()) {
+				lenient().when(resultSet.getString(column.getKey())).thenReturn(column.getValue());
+			}
 		}
 		return resultSet;
 	}

From e4237e83bfb17e2b2746385374c5f22a07fc1cf3 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Thu, 20 Jul 2023 12:32:09 +0300
Subject: [PATCH 12/15] FIR-25124 Removed /dynamic/query path for system engine
 in JDBC

---
 .../com/firebolt/jdbc/client/query/StatementClientImpl.java  | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
index af06cfc93..11e2e7c94 100644
--- a/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
+++ b/src/main/java/com/firebolt/jdbc/client/query/StatementClientImpl.java
@@ -36,9 +36,6 @@ public class StatementClientImpl extends FireboltClient implements StatementClie
 
 	private static final String TAB_SEPARATED_WITH_NAMES_AND_TYPES_FORMAT = "TabSeparatedWithNamesAndTypes";
 
-	private static final List<String> URI_QUERY_SEGMENTS = Arrays.asList("dynamic","query");
-
-
 	private final BiPredicate<Call, String> isCallWithId = (call, id) -> call.request().tag() instanceof String
 			&& StringUtils.equals((String) call.request().tag(), id);
 
@@ -175,7 +172,7 @@ public boolean isStatementRunning(String statementId) {
 	}
 
 	private URI buildQueryUri(FireboltProperties fireboltProperties, Map<String, String> parameters) {
-		return buildURI(fireboltProperties, parameters, PropertyUtil.isLocalDb(fireboltProperties) || !fireboltProperties.isSystemEngine() ? Collections.emptyList() : URI_QUERY_SEGMENTS);
+		return buildURI(fireboltProperties, parameters, Collections.emptyList());
 	}
 
 	private URI buildCancelUri(FireboltProperties fireboltProperties, String id) {

From 798962424a5403e3bbdaa04dd6d05b8888c48850 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Thu, 20 Jul 2023 12:33:02 +0300
Subject: [PATCH 13/15] changed TimeoutTest that stopped working in current
 version

---
 .../java/integration/tests/TimeoutTest.java           | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/integrationTest/java/integration/tests/TimeoutTest.java b/src/integrationTest/java/integration/tests/TimeoutTest.java
index 6fcca31c7..81b72be2a 100644
--- a/src/integrationTest/java/integration/tests/TimeoutTest.java
+++ b/src/integrationTest/java/integration/tests/TimeoutTest.java
@@ -3,8 +3,11 @@
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.sql.Connection;
+import java.sql.SQLException;
 import java.sql.Statement;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
@@ -17,12 +20,12 @@ class TimeoutTest extends IntegrationTest {
 
 	@Test
 	@Timeout(value = 7, unit = TimeUnit.MINUTES)
-	void shouldExecuteRequestWithoutTimeout() {
+	void shouldExecuteRequestWithoutTimeout() throws SQLException {
 		long startTime = System.nanoTime();
 		try (Connection con = this.createConnection(); Statement stmt = con.createStatement()) {
-			this.setParam(con, "use_standard_sql", "0");
-			this.setParam(con, "advanced_mode", "1");
-			stmt.executeQuery("SELECT sleepEachRow(1) from numbers(360)");
+			String numbers = IntStream.range(1, 10_000).boxed().map(String::valueOf).collect(Collectors.joining(","));
+			String query = String.format("WITH arr AS (SELECT [%s] as a)%nSELECT md5(md5(md5(md5(md5(md5(md5(to_string(a)))))))) FROM arr UNNEST(a)", numbers);
+			stmt.executeQuery(query);
 		} catch (Exception e) {
 			log.error("Error", e);
 			fail();

From 3ff508c97c2be9a1bfc72f63d2d7864b96256453 Mon Sep 17 00:00:00 2001
From: alexradzin <alexander.radzin@firebolt.io>
Date: Thu, 20 Jul 2023 12:40:16 +0300
Subject: [PATCH 14/15] FIR-25124 Removed /dynamic/query path for system engine
 in JDBC - fixed unit test

---
 .../com/firebolt/jdbc/client/query/StatementClientImplTest.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
index f9f12943d..044a092dd 100644
--- a/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
+++ b/src/test/java/com/firebolt/jdbc/client/query/StatementClientImplTest.java
@@ -55,7 +55,7 @@ void shouldPostSqlQueryWithExpectedUrl() throws FireboltException, IOException {
 	void shouldPostSqlQueryForSystemEngine() throws FireboltException, IOException {
 		String url = shouldPostSqlQueryForSystemEngine(true).getValue();
 		assertEquals(
-				"http://firebolt1:555/dynamic/query?result_overflow_mode=break&database=db1&account_id=12345&output_format=TabSeparatedWithNamesAndTypes&max_result_rows=1&max_execution_time=15",
+				"http://firebolt1:555/?result_overflow_mode=break&database=db1&account_id=12345&output_format=TabSeparatedWithNamesAndTypes&max_result_rows=1&max_execution_time=15",
 				url);
 	}
 

From 218ec2e3fad655233e5cc7c7b0daf32e5747e330 Mon Sep 17 00:00:00 2001
From: Stepan Burlakov <stepansergeevitch@gmail.com>
Date: Thu, 20 Jul 2023 15:33:43 +0300
Subject: [PATCH 15/15] ci: new identity (#245)

---
 .github/workflows/integration-test.yml | 47 ++++++++++++++++----------
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml
index d6148db1e..8b8ad9d6d 100644
--- a/.github/workflows/integration-test.yml
+++ b/.github/workflows/integration-test.yml
@@ -8,12 +8,12 @@ on:
         required: false
         default: ''
       engine:
-        description: 'Engine'
-        required: true
+        description: 'Engine - a new one will be created if not provided'
+        required: false
       account:
         description: 'Account'
         required: true
-        default: 'integration'
+        default: 'developer'
       environment:
         description: 'Environment to run the tests against'
         type: choice
@@ -28,6 +28,13 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
+      - name: Validate database and engine
+        if: ${{ (github.event.inputs.database == '') != (github.event.inputs.engine == '') }}
+        uses: actions/github-script@v3
+        with:
+          script: |
+            core.setFailed("Database and Engine parameters should be provided simultaneously")
+
       - name: "Foresight: Collect Workflow Telemetry"
         uses: runforesight/foresight-workflow-kit-action@v1
         if: ${{ always() }}
@@ -42,25 +49,22 @@ jobs:
       - name: Determine env variables
         run: |
           if [ "${{ github.event.inputs.environment }}" == 'staging' ]; then
-             echo "USERNAME=${{ secrets.FIREBOLT_USERNAME_STAGING }}" >> "$GITHUB_ENV"
-             echo "PASSWORD=${{ secrets.FIREBOLT_PASSWORD_STAGING }}" >> "$GITHUB_ENV"
-             echo "SERVICE_ACCOUNT_ID=${{ secrets.SERVICE_ACCOUNT_ID_STAGING }}" >> "$GITHUB_ENV"
-             echo "SERVICE_ACCOUNT_SECRET=${{ secrets.SERVICE_ACCOUNT_SECRET_STAGING }}" >> "$GITHUB_ENV"
+             echo "SERVICE_ACCOUNT_ID=${{ secrets.FIREBOLT_CLIENT_ID_STG_NEW_IDN }}" >> "$GITHUB_ENV"
+             echo "SERVICE_ACCOUNT_SECRET=${{ secrets.FIREBOLT_CLIENT_SECRET_STG_NEW_IDN }}" >> "$GITHUB_ENV"
           else
-             echo "USERNAME=${{ secrets.FIREBOLT_USERNAME_DEV }}" >> "$GITHUB_ENV"
-             echo "PASSWORD=${{ secrets.FIREBOLT_PASSWORD_DEV }}" >> "$GITHUB_ENV"
-             echo "SERVICE_ACCOUNT_ID=${{ secrets.SERVICE_ACCOUNT_ID_DEV }}" >> "$GITHUB_ENV"
-             echo "SERVICE_ACCOUNT_SECRET=${{ secrets.SERVICE_ACCOUNT_SECRET_DEV }}" >> "$GITHUB_ENV"
+             echo "SERVICE_ACCOUNT_ID=${{ secrets.FIREBOLT_CLIENT_ID_NEW_IDN }}" >> "$GITHUB_ENV"
+             echo "SERVICE_ACCOUNT_SECRET=${{ secrets.FIREBOLT_CLIENT_SECRET_NEW_IDN }}" >> "$GITHUB_ENV"
           fi
+
       - name: Setup database and engine
         id: setup
         if: ${{ github.event.inputs.database == '' }}
-        uses: firebolt-db/integration-testing-setup@v1
+        uses: firebolt-db/integration-testing-setup@v2
         with:
-          firebolt-username: ${{ env.USERNAME }}
-          firebolt-password: ${{ env.PASSWORD }}
+          firebolt-client-id: ${{ env.SERVICE_ACCOUNT_ID }}
+          firebolt-client-secret: ${{ env.SERVICE_ACCOUNT_SECRET }}
+          account: ${{ github.event.inputs.account }}
           api-endpoint: "api.${{ github.event.inputs.environment }}.firebolt.io"
-          region: "us-east-1"
           instance-type: "B2"
 
       - name: Determine database name
@@ -72,8 +76,17 @@ jobs:
              echo "database_name=${{ steps.setup.outputs.database_name }}" >> $GITHUB_OUTPUT
           fi
 
+      - name: Determine engine name
+        id: find-engine-name
+        run: |
+          if ! [[ -z "${{ github.event.inputs.engine }}" ]]; then
+             echo "engine_name=${{ github.event.inputs.engine }}" >> $GITHUB_OUTPUT
+          else
+             echo "engine_name=${{ steps.setup.outputs.engine_name }}" >> $GITHUB_OUTPUT
+          fi
+
       - name: Run integration tests
-        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }}" -Daccount="${{ github.event.inputs.account }}" -Dengine="${{ github.event.inputs.engine }}"
+        run: ./gradlew integrationTest -Ddb=${{ steps.find-database-name.outputs.database_name }} -Denv=${{ github.event.inputs.environment }} -Dclient_secret="${{ env.SERVICE_ACCOUNT_SECRET }}" -Dclient_id="${{ env.SERVICE_ACCOUNT_ID }}" -Daccount="${{ github.event.inputs.account }}" -Dengine="${{ steps.find-engine-name.outputs.engine_name }}"
 
       - name: "Foresight: Analyze Test Results"
         uses: runforesight/foresight-test-kit-action@v1
@@ -84,4 +97,4 @@ jobs:
           test_path: ./build/test-results/
           tags: |
             type:"integration"
-            language:"Java"
\ No newline at end of file
+            language:"Java"