ValidationSqliteUtilTest.java

  1. package zserio.runtime.validation;

  2. import static org.hamcrest.CoreMatchers.anyOf;
  3. import static org.hamcrest.CoreMatchers.is;
  4. import static org.hamcrest.MatcherAssert.assertThat;
  5. import static org.junit.jupiter.api.Assertions.assertEquals;
  6. import static org.junit.jupiter.api.Assertions.assertFalse;
  7. import static org.junit.jupiter.api.Assertions.assertTrue;

  8. import java.sql.Connection;
  9. import java.sql.DriverManager;
  10. import java.sql.ResultSet;
  11. import java.sql.ResultSetMetaData;
  12. import java.sql.SQLException;
  13. import java.sql.Statement;
  14. import java.sql.Types;
  15. import java.util.Map;
  16. import java.util.Properties;

  17. import org.junit.jupiter.api.Test;

  18. import zserio.runtime.SqlDatabaseReader;

  19. public class ValidationSqliteUtilTest
  20. {
  21.     static
  22.     {
  23.         try
  24.         {
  25.             Class.forName("org.sqlite.JDBC");
  26.         }
  27.         catch (ClassNotFoundException excpt)
  28.         {
  29.             throw new RuntimeException("Can't register SQLite JDBC driver!");
  30.         }
  31.     }

  32.     @Test
  33.     public void getColumnTypes() throws SQLException
  34.     {
  35.         final String TABLE_NAME = "ColumnTypesTestTable";

  36.         try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
  37.         {
  38.             testDatabase.executeUpdate("CREATE TABLE " + TABLE_NAME +
  39.                     "(col1 TEXT, col2 INTEGER NOT NULL PRIMARY KEY, col3 BLOB);");
  40.             final Map<String, ValidationSqliteUtil.ColumnDescription> schema =
  41.                     ValidationSqliteUtil.getTableSchema(testDatabase.connection(), null, TABLE_NAME);

  42.             final ValidationSqliteUtil.ColumnDescription col1 = schema.remove("col1");
  43.             assertEquals("col1", col1.getName());
  44.             assertEquals("TEXT", col1.getType());
  45.             assertEquals(false, col1.isNotNull());
  46.             assertEquals(false, col1.isPrimaryKey());

  47.             final ValidationSqliteUtil.ColumnDescription col2 = schema.remove("col2");
  48.             assertEquals("col2", col2.getName());
  49.             assertEquals("INTEGER", col2.getType());
  50.             assertEquals(true, col2.isNotNull());
  51.             assertEquals(true, col2.isPrimaryKey());

  52.             final ValidationSqliteUtil.ColumnDescription col3 = schema.remove("col3");
  53.             assertEquals("col3", col3.getName());
  54.             assertEquals("BLOB", col3.getType());
  55.             assertEquals(false, col3.isNotNull());
  56.             assertEquals(false, col3.isPrimaryKey());

  57.             assertTrue(schema.isEmpty());
  58.         }
  59.     }

  60.     @Test
  61.     public void isHiddenColumnInTable() throws SQLException
  62.     {
  63.         final String TABLE_NAME = "HiddenColumnTestTable";

  64.         try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
  65.         {
  66.             testDatabase.executeUpdate("CREATE VIRTUAL TABLE " + TABLE_NAME + " USING fts4 "
  67.                     + "(substitutionId TEXT NOT NULL);");
  68.             assertTrue(ValidationSqliteUtil.isHiddenColumnInTable(
  69.                     testDatabase.connection(), null, TABLE_NAME, "docId"));
  70.             assertFalse(ValidationSqliteUtil.isHiddenColumnInTable(
  71.                     testDatabase.connection(), null, TABLE_NAME, "languageCode"));
  72.         }
  73.     }

  74.     @Test
  75.     public void sqlTypeToSqliteType() throws SQLException
  76.     {
  77.         final String tableName = "sqlTypeToSqliteTypeTable";
  78.         try (final TestSqlDatabase testDatabase = new TestSqlDatabase())
  79.         {
  80.             testDatabase.executeUpdate("CREATE TABLE " + tableName + "(id INTEGER PRIMARY KEY, "
  81.                     + "integerCol INTEGER, realCol REAL, textCol TEXT, blobCol BLOB)");

  82.             testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (0, NULL, NULL, NULL, NULL)");
  83.             testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (1, 13, 1.3, 'STRING', x'00')");
  84.             testDatabase.executeUpdate("INSERT INTO " + tableName + " VALUES (2, 1.3, 'STRING', x'00', 13)");
  85.             try (final Statement stmt = testDatabase.connection().createStatement();
  86.                     final ResultSet resultSet = stmt.executeQuery("SELECT * FROM " + tableName);)
  87.             {
  88.                 // first row checks NULL values
  89.                 // note that different versions of Xerial JDBC returns different types
  90.                 assertTrue(resultSet.next());
  91.                 ResultSetMetaData metaData = resultSet.getMetaData();
  92.                 assertEquals(
  93.                         Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
  94.                 assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)),
  95.                         anyOf(is(Types.INTEGER), is(Types.NULL)));
  96.                 assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)),
  97.                         anyOf(is(Types.REAL), is(Types.NULL)));
  98.                 assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)),
  99.                         anyOf(is(Types.VARCHAR), is(Types.NULL)));
  100.                 assertThat(ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)),
  101.                         anyOf(is(Types.BLOB), is(Types.NULL)));

  102.                 // second row checks correct values
  103.                 assertTrue(resultSet.next());
  104.                 metaData = resultSet.getMetaData();
  105.                 assertEquals(
  106.                         Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
  107.                 assertEquals(
  108.                         Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)));
  109.                 assertEquals(Types.REAL, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)));
  110.                 assertEquals(
  111.                         Types.VARCHAR, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)));
  112.                 assertEquals(Types.BLOB, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)));

  113.                 // third row checks types mismatch - i.e. checks dynamic typing in SQLite
  114.                 assertTrue(resultSet.next());
  115.                 metaData = resultSet.getMetaData();
  116.                 assertEquals(
  117.                         Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(1)));
  118.                 assertEquals(Types.REAL, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(2)));
  119.                 assertEquals(
  120.                         Types.VARCHAR, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(3)));
  121.                 assertEquals(Types.BLOB, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(4)));
  122.                 assertEquals(
  123.                         Types.INTEGER, ValidationSqliteUtil.sqlTypeToSqliteType(metaData.getColumnType(5)));
  124.             }
  125.         }
  126.     }

  127.     private static final class TestSqlDatabase implements SqlDatabaseReader
  128.     {
  129.         public TestSqlDatabase() throws SQLException
  130.         {
  131.             final String uriPath = "jdbc:sqlite::memory:";
  132.             final Properties connectionProps = new Properties();
  133.             connectionProps.setProperty("flags", "CREATE");

  134.             connection = DriverManager.getConnection(uriPath, connectionProps);
  135.         }

  136.         @Override
  137.         public void close() throws SQLException
  138.         {
  139.             connection.close();
  140.         }

  141.         @Override
  142.         public Connection connection()
  143.         {
  144.             return connection;
  145.         }

  146.         public void executeUpdate(String sql) throws SQLException
  147.         {
  148.             try (final Statement statement = connection.createStatement())
  149.             {
  150.                 statement.executeUpdate(sql);
  151.             }
  152.         }

  153.         private final Connection connection;
  154.     }
  155. }