Skip to content

Commit

Permalink
feat: FIR-33601: use catalogs table instead of databases table if exi…
Browse files Browse the repository at this point in the history
…sts (#424)
  • Loading branch information
alexradzin authored Jun 19, 2024
1 parent 07a4dc5 commit 21e5f3c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private FireboltProperties getSessionPropertiesForSystemEngine(String accessToke



private FireboltEngineService getFireboltEngineService() {
private FireboltEngineService getFireboltEngineService() throws SQLException {
if (fireboltEngineService == null) {
int currentInfraVersion = Optional.ofNullable(loginProperties.getAdditionalProperties().get("infraVersion")).map(Integer::parseInt).orElse(infraVersion);
fireboltEngineService = currentInfraVersion >= 2 ? new FireboltEngineVersion2Service(this) : new FireboltEngineInformationSchemaService(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.firebolt.jdbc.connection.FireboltConnection;
import com.firebolt.jdbc.connection.settings.FireboltProperties;
import com.firebolt.jdbc.exception.FireboltException;
import lombok.RequiredArgsConstructor;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
Expand All @@ -17,29 +16,38 @@
import static java.lang.String.format;
import static java.util.stream.Collectors.toCollection;

@RequiredArgsConstructor
public class FireboltEngineInformationSchemaService implements FireboltEngineService {
private static final String ENGINE_URL = "url";
private static final String STATUS_FIELD = "status";
private static final String ENGINE_NAME_FIELD = "engine_name";
private static final Collection<String> RUNNING_STATUSES = Stream.of("running", "ENGINE_STATE_RUNNING").collect(toCollection(() -> new TreeSet<>(CASE_INSENSITIVE_ORDER)));
private static final String ENGINE_QUERY =
"SELECT engs.url, engs.attached_to, dbs.database_name, engs.status, engs.engine_name " +
"SELECT engs.url, engs.attached_to, dbs.%1$s_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 " +
"LEFT JOIN information_schema.%1$ss as dbs ON engs.attached_to = dbs.%1$s_name " +
"WHERE engs.engine_name = ?";
private static final String DATABASE_QUERY = "SELECT database_name FROM information_schema.databases WHERE database_name=?";
private static final String INVENTORY_QUERY = "SELECT %1$s_name FROM information_schema.%1$ss WHERE %1$s_name=?";

private final FireboltConnection fireboltConnection;
private final String dbTerm;

public FireboltEngineInformationSchemaService(FireboltConnection fireboltConnection) throws SQLException {
this.fireboltConnection = fireboltConnection;
dbTerm = doesRecordExist(format(INVENTORY_QUERY, "table"), "catalogs") ? "catalog" : "database";
}

@Override
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();
}
}
return doesRecordExist(format(INVENTORY_QUERY, dbTerm), database);
}

private boolean doesRecordExist(String query, String param) throws SQLException {
try (PreparedStatement ps = fireboltConnection.prepareStatement(query)) {
ps.setString(1, param);
try (ResultSet rs = ps.executeQuery()) {
return rs.next();
}
}
}

@Override
Expand All @@ -49,7 +57,7 @@ public Engine getEngine(FireboltProperties properties) throws SQLException {
if (engine == null) {
throw new IllegalArgumentException("Cannot retrieve engine parameters because its name is null");
}
try (PreparedStatement ps = fireboltConnection.prepareStatement(ENGINE_QUERY)) {
try (PreparedStatement ps = fireboltConnection.prepareStatement(format(ENGINE_QUERY, dbTerm))) {
ps.setString(1, engine);
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
import com.firebolt.jdbc.connection.FireboltConnection;
import com.firebolt.jdbc.connection.settings.FireboltProperties;
import com.firebolt.jdbc.exception.FireboltException;
import org.junit.jupiter.api.BeforeEach;
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;
Expand All @@ -30,13 +30,27 @@
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class FireboltEngineInformationSchemaServiceTest {
abstract class FireboltEngineInformationSchemaServiceTest {

@InjectMocks
private FireboltEngineInformationSchemaService fireboltEngineService;
protected FireboltEngineInformationSchemaService fireboltEngineService;

@Mock
private FireboltConnection fireboltConnection;
protected FireboltConnection fireboltConnection;
private final boolean useCatalogTable;

FireboltEngineInformationSchemaServiceTest(boolean useCatalogTable) {
this.useCatalogTable = useCatalogTable;
}

@BeforeEach
void init() throws SQLException {
PreparedStatement catalogsStatement = mock(PreparedStatement.class);
Map<String, String> catalogsRsData = useCatalogTable ? Map.of("table_name", "catalogs") : Map.of();
ResultSet catalogsResultSet = mockedResultSet(catalogsRsData);
when(fireboltConnection.prepareStatement("SELECT table_name FROM information_schema.tables WHERE table_name=?")).thenReturn(catalogsStatement);
when(catalogsStatement.executeQuery()).thenReturn(catalogsResultSet);
fireboltEngineService = new FireboltEngineInformationSchemaService(fireboltConnection);
}

@Test
void shouldThrowExceptionEngineWhenEngineNameIsNotProvided() {
Expand Down Expand Up @@ -86,18 +100,6 @@ void shouldThrowExceptionWhenSomethingIsWrong(String engineName, String db, Stri
Mockito.verify(statement, Mockito.times(1)).setString(1, engineName);
}

@ParameterizedTest
@CsvSource(value = {"mydb;'';false", "other_db;'database_name,other_db';true"}, delimiter = ';')
void doesDatabaseExist(String db, String row, boolean expected) throws SQLException {
PreparedStatement statement = mock(PreparedStatement.class);
Map<String, String> rowData = row == null || row.isEmpty() ? Map.of() : Map.of(row.split(",")[0], row.split(",")[1]);
ResultSet resultSet = mockedResultSet(rowData);
when(fireboltConnection.prepareStatement("SELECT database_name FROM information_schema.databases WHERE database_name=?")).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
assertEquals(expected, fireboltEngineService.doesDatabaseExist(db));
Mockito.verify(statement, Mockito.times(1)).setString(1, db);
}

private PreparedStatement mockedEntityStatement(String entity, String row) throws SQLException {
if (row == null) {
return null;
Expand All @@ -109,7 +111,7 @@ private PreparedStatement mockedEntityStatement(String entity, String row) throw
return statement;
}

private ResultSet mockedResultSet(Map<String, String> values) throws SQLException {
protected ResultSet mockedResultSet(Map<String, String> values) throws SQLException {
ResultSet resultSet = mock(ResultSet.class);
if (values == null || values.isEmpty()) {
when(resultSet.next()).thenReturn(false);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.firebolt.jdbc.service;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.mockito.Mockito;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class FireboltEngineInformationSchemaServiceUsingCatalogsTableTest extends FireboltEngineInformationSchemaServiceTest{
FireboltEngineInformationSchemaServiceUsingCatalogsTableTest() {
super(true);
}

@ParameterizedTest
@CsvSource(value = {"mydb;'';false", "other_db;'database_name,other_db';true"}, delimiter = ';')
void doesDatabaseExist(String db, String row, boolean expected) throws SQLException {
PreparedStatement statement = mock(PreparedStatement.class);
Map<String, String> rowData = row == null || row.isEmpty() ? Map.of() : Map.of(row.split(",")[0], row.split(",")[1]);
ResultSet resultSet = mockedResultSet(rowData);
when(fireboltConnection.prepareStatement("SELECT catalog_name FROM information_schema.catalogs WHERE catalog_name=?")).thenReturn(statement);
when(statement.executeQuery()).thenReturn(resultSet);
assertEquals(expected, fireboltEngineService.doesDatabaseExist(db));
Mockito.verify(statement, Mockito.times(1)).setString(1, db);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.firebolt.jdbc.service;

class FireboltEngineInformationSchemaServiceUsingDatabasesTableTest extends FireboltEngineInformationSchemaServiceTest{
FireboltEngineInformationSchemaServiceUsingDatabasesTableTest() {
super(false);
}
}

0 comments on commit 21e5f3c

Please sign in to comment.