ValidationSqliteUtilTest.java
package zserio.runtime.validation;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.Map;
import java.util.Properties;
import org.junit.jupiter.api.Test;
import zserio.runtime.SqlDatabaseReader;
public class ValidationSqliteUtilTest
{
static
{
try
{
Class.forName("org.sqlite.JDBC");
}
catch (ClassNotFoundException excpt)
{
throw new RuntimeException("Can't register SQLite JDBC driver!");
}
}
@Test
public void getColumnTypes() throws SQLException
{
final String TABLE_NAME = "ColumnTypesTestTable";
try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
{
testDatabase.executeUpdate("CREATE TABLE " + TABLE_NAME +
"(col1 TEXT, col2 INTEGER NOT NULL PRIMARY KEY, col3 BLOB);");
final Map<String, ValidationSqliteUtil.ColumnDescription> schema =
ValidationSqliteUtil.getTableSchema(testDatabase.connection(), null, TABLE_NAME);
final ValidationSqliteUtil.ColumnDescription col1 = schema.remove("col1");
assertEquals("col1", col1.getName());
assertEquals("TEXT", col1.getType());
assertEquals(false, col1.isNotNull());
assertEquals(false, col1.isPrimaryKey());
final ValidationSqliteUtil.ColumnDescription col2 = schema.remove("col2");
assertEquals("col2", col2.getName());
assertEquals("INTEGER", col2.getType());
assertEquals(true, col2.isNotNull());
assertEquals(true, col2.isPrimaryKey());
final ValidationSqliteUtil.ColumnDescription col3 = schema.remove("col3");
assertEquals("col3", col3.getName());
assertEquals("BLOB", col3.getType());
assertEquals(false, col3.isNotNull());
assertEquals(false, col3.isPrimaryKey());
assertTrue(schema.isEmpty());
}
}
@Test
public void isHiddenColumnInTable() throws SQLException
{
final String TABLE_NAME = "HiddenColumnTestTable";
try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
{
testDatabase.executeUpdate("CREATE VIRTUAL TABLE " + TABLE_NAME + " USING fts4 "
+ "(substitutionId TEXT NOT NULL);");
assertTrue(ValidationSqliteUtil.isHiddenColumnInTable(
testDatabase.connection(), null, TABLE_NAME, "docId"));
assertFalse(ValidationSqliteUtil.isHiddenColumnInTable(
testDatabase.connection(), null, TABLE_NAME, "languageCode"));
}
}
@Test
public void sqlTypeToSqliteType() throws SQLException
{
final String tableName = "sqlTypeToSqliteTypeTable";
try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
{
testDatabase.executeUpdate("CREATE TABLE " + tableName + "(id INTEGER PRIMARY KEY, "
+ "integerCol INTEGER, realCol REAL, textCol TEXT, blobCol BLOB)");
testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (0, NULL, NULL, NULL, NULL)");
testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (1, 13, 1.3, 'STRING', x'00')");
testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (2, 1.3, 'STRING', x'00', 13)");
try (final Statement stmt = testDatabase.connection().createStatement();
final ResultSet resultSet = stmt.executeQuery("SELECT * FROM " + tableName);)
{
// first row checks NULL values
// note that different versions of Xerial JDBC returns different types
assertTrue(resultSet.next());
ResultSetMetaData metaData = resultSet.getMetaData();
assertEquals(
Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)),
anyOf(is(Types.INTEGER), is(Types.NULL)));
assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)),
anyOf(is(Types.REAL), is(Types.NULL)));
assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)),
anyOf(is(Types.VARCHAR), is(Types.NULL)));
assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)),
anyOf(is(Types.BLOB), is(Types.NULL)));
// second row checks correct values
assertTrue(resultSet.next());
metaData = resultSet.getMetaData();
assertEquals(
Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
assertEquals(
Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)));
assertEquals(Types.REAL, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)));
assertEquals(
Types.VARCHAR, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)));
assertEquals(Types.BLOB, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)));
// third row checks types mismatch - i.e. checks dynamic typing in SQLite
assertTrue(resultSet.next());
metaData = resultSet.getMetaData();
assertEquals(
Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
assertEquals(Types.REAL, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)));
assertEquals(
Types.VARCHAR, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)));
assertEquals(Types.BLOB, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)));
assertEquals(
Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)));
}
}
}
private static final class TestSqlDatabase implements SqlDatabaseReader
{
public TestSqlDatabase() throws SQLException
{
final String uriPath = "jdbc:sqlite::memory:";
final Properties connectionProps = new Properties();
connectionProps.setProperty("flags", "CREATE");
connection = DriverManager.getConnection(uriPath, connectionProps);
}
@Override
public void close() throws SQLException
{
connection.close();
}
@Override
public Connection connection()
{
return connection;
}
public void executeUpdate(String sql) throws SQLException
{
try (final Statement statement = connection.createStatement())
{
statement.executeUpdate(sql);
}
}
private final Connection connection;
}
}