@Before
 public void setupOnce() throws Exception {
   nativeMeta = new ConcreteBaseDatabaseMeta();
   nativeMeta.setAccessType(DatabaseMeta.TYPE_ACCESS_NATIVE);
   odbcMeta = new ConcreteBaseDatabaseMeta();
   nativeMeta.setAccessType(DatabaseMeta.TYPE_ACCESS_ODBC);
   jndiMeta = new ConcreteBaseDatabaseMeta();
   KettleClientEnvironment.init();
 }
 @Test
 public void testCheckIndexExists() throws Exception {
   Database db = Mockito.mock(Database.class);
   ResultSet rs = Mockito.mock(ResultSet.class);
   DatabaseMetaData dmd = Mockito.mock(DatabaseMetaData.class);
   DatabaseMeta dm = Mockito.mock(DatabaseMeta.class);
   Mockito.when(dm.getQuotedSchemaTableCombination("", "FOO")).thenReturn("FOO");
   Mockito.when(rs.next())
       .thenAnswer(
           new Answer<Boolean>() {
             public Boolean answer(InvocationOnMock invocation) throws Throwable {
               rowCnt++;
               return new Boolean(rowCnt < 3);
             }
           });
   Mockito.when(db.getDatabaseMetaData()).thenReturn(dmd);
   Mockito.when(dmd.getIndexInfo(null, null, "FOO", false, true)).thenReturn(rs);
   Mockito.when(rs.getString("COLUMN_NAME"))
       .thenAnswer(
           new Answer<String>() {
             @Override
             public String answer(InvocationOnMock invocation) throws Throwable {
               if (rowCnt == 1) {
                 return "ROW1COL2";
               } else if (rowCnt == 2) {
                 return "ROW2COL2";
               } else {
                 return null;
               }
             }
           });
   Mockito.when(db.getDatabaseMeta()).thenReturn(dm);
   assertTrue(odbcMeta.checkIndexExists(db, "", "FOO", new String[] {"ROW1COL2", "ROW2COL2"}));
   assertFalse(odbcMeta.checkIndexExists(db, "", "FOO", new String[] {"ROW2COL2", "NOTTHERE"}));
   assertFalse(odbcMeta.checkIndexExists(db, "", "FOO", new String[] {"NOTTHERE", "ROW1COL2"}));
 }
 @SuppressWarnings("deprecation")
 @Test
 public void testDeprecatedItems() throws Exception {
   assertEquals(
       "'2016-08-11'",
       nativeMeta.getSQLValue(new ValueMetaDate("FOO"), new Date(116, 7, 11), "YYYY-MM-dd"));
   assertEquals(
       "\"FOO\".\"BAR\"", nativeMeta.getBackwardsCompatibleSchemaTableCombination("FOO", "BAR"));
   assertEquals(
       "\"null\".\"BAR\"",
       nativeMeta.getBackwardsCompatibleSchemaTableCombination(
           null, "BAR")); // not sure this is right ...
   assertEquals(
       "FOO\".\"BAR\"", nativeMeta.getBackwardsCompatibleSchemaTableCombination("FOO\"", "BAR"));
   assertEquals(
       "FOO\".BAR\"", nativeMeta.getBackwardsCompatibleSchemaTableCombination("FOO\"", "BAR\""));
   assertEquals("\"FOO\"", nativeMeta.getBackwardsCompatibleTable("FOO"));
   assertEquals(
       "\"null\"",
       nativeMeta.getBackwardsCompatibleTable(null)); // not sure this should happen but it does
   assertEquals("FOO\"", nativeMeta.getBackwardsCompatibleTable("FOO\""));
   assertEquals("\"FOO", nativeMeta.getBackwardsCompatibleTable("\"FOO"));
 }
 @Test
 public void testDefaultSettings() throws Exception {
   // Note - this method should only use native or odbc.
   // The jndi meta is used for mutations of the meta, and it would
   // not be threadsafe in a multi-threaded testing environment
   // (each test run in its own thread).
   assertEquals(-1, nativeMeta.getDefaultDatabasePort());
   assertTrue(nativeMeta.supportsSetCharacterStream());
   assertTrue(nativeMeta.supportsAutoInc());
   assertEquals("", nativeMeta.getLimitClause(5));
   assertEquals(0, nativeMeta.getNotFoundTK(true));
   assertEquals("", nativeMeta.getSQLNextSequenceValue("FOO"));
   assertEquals("", nativeMeta.getSQLCurrentSequenceValue("FOO"));
   assertEquals("", nativeMeta.getSQLSequenceExists("FOO"));
   assertTrue(nativeMeta.isFetchSizeSupported());
   assertFalse(nativeMeta.needsPlaceHolder());
   assertTrue(nativeMeta.supportsSchemas());
   assertTrue(nativeMeta.supportsCatalogs());
   assertTrue(nativeMeta.supportsEmptyTransactions());
   assertEquals("SUM", nativeMeta.getFunctionSum());
   assertEquals("AVG", nativeMeta.getFunctionAverage());
   assertEquals("MIN", nativeMeta.getFunctionMinimum());
   assertEquals("MAX", nativeMeta.getFunctionMaximum());
   assertEquals("COUNT", nativeMeta.getFunctionCount());
   assertEquals("\"", nativeMeta.getStartQuote());
   assertEquals("\"", nativeMeta.getEndQuote());
   assertEquals("FOO.BAR", nativeMeta.getSchemaTableCombination("FOO", "BAR"));
   assertEquals(DatabaseMeta.CLOB_LENGTH, nativeMeta.getMaxTextFieldLength());
   assertEquals(DatabaseMeta.CLOB_LENGTH, nativeMeta.getMaxVARCHARLength());
   assertTrue(nativeMeta.supportsTransactions());
   assertFalse(nativeMeta.supportsSequences());
   assertTrue(nativeMeta.supportsBitmapIndex());
   assertTrue(nativeMeta.supportsSetLong());
   assertArrayEquals(new String[] {}, nativeMeta.getReservedWords());
   assertTrue(nativeMeta.quoteReservedWords());
   assertFalse(nativeMeta.supportsRepository());
   assertArrayEquals(new String[] {"TABLE"}, nativeMeta.getTableTypes());
   assertArrayEquals(new String[] {"VIEW"}, nativeMeta.getViewTypes());
   assertArrayEquals(new String[] {"SYNONYM"}, nativeMeta.getSynonymTypes());
   assertFalse(nativeMeta.useSchemaNameForTableList());
   assertTrue(nativeMeta.supportsViews());
   assertFalse(nativeMeta.supportsSynonyms());
   assertNull(nativeMeta.getSQLListOfProcedures());
   assertNull(nativeMeta.getSQLListOfSequences());
   assertTrue(nativeMeta.supportsFloatRoundingOnUpdate());
   assertNull(nativeMeta.getSQLLockTables(new String[] {"FOO"}));
   assertNull(nativeMeta.getSQLUnlockTables(new String[] {"FOO"}));
   assertTrue(nativeMeta.supportsTimeStampToDateConversion());
   assertTrue(nativeMeta.supportsBatchUpdates());
   assertFalse(nativeMeta.supportsBooleanDataType());
   assertFalse(nativeMeta.supportsTimestampDataType());
   assertTrue(nativeMeta.preserveReservedCase());
   assertTrue(nativeMeta.isDefaultingToUppercase());
   Map<String, String> emptyMap = new HashMap<String, String>();
   assertEquals(emptyMap, nativeMeta.getExtraOptions());
   assertEquals(";", nativeMeta.getExtraOptionSeparator());
   assertEquals("=", nativeMeta.getExtraOptionValueSeparator());
   assertEquals(";", nativeMeta.getExtraOptionIndicator());
   assertTrue(nativeMeta.supportsOptionsInURL());
   assertNull(nativeMeta.getExtraOptionsHelpText());
   assertTrue(nativeMeta.supportsGetBlob());
   assertNull(nativeMeta.getConnectSQL());
   assertTrue(nativeMeta.supportsSetMaxRows());
   assertFalse(nativeMeta.isUsingConnectionPool());
   assertEquals(ConnectionPoolUtil.defaultMaximumNrOfConnections, nativeMeta.getMaximumPoolSize());
   assertEquals(ConnectionPoolUtil.defaultInitialNrOfConnections, nativeMeta.getInitialPoolSize());
   assertFalse(nativeMeta.isPartitioned());
   assertArrayEquals(new PartitionDatabaseMeta[0], nativeMeta.getPartitioningInformation());
   Properties emptyProps = new Properties();
   assertEquals(emptyProps, nativeMeta.getConnectionPoolingProperties());
   assertTrue(nativeMeta.needsToLockAllTables());
   assertTrue(nativeMeta.isStreamingResults());
   assertFalse(nativeMeta.isQuoteAllFields());
   assertFalse(nativeMeta.isForcingIdentifiersToLowerCase());
   assertFalse(nativeMeta.isForcingIdentifiersToUpperCase());
   assertFalse(nativeMeta.isUsingDoubleDecimalAsSchemaTableSeparator());
   assertTrue(nativeMeta.isRequiringTransactionsOnQueries());
   assertEquals(
       "org.pentaho.di.core.database.DatabaseFactory", nativeMeta.getDatabaseFactoryName());
   assertNull(nativeMeta.getPreferredSchemaName());
   assertFalse(nativeMeta.supportsSequenceNoMaxValueOption());
   assertFalse(nativeMeta.requiresCreateTablePrimaryKeyAppend());
   assertFalse(nativeMeta.requiresCastToVariousForIsNull());
   assertFalse(nativeMeta.isDisplaySizeTwiceThePrecision());
   assertTrue(nativeMeta.supportsPreparedStatementMetadataRetrieval());
   assertFalse(nativeMeta.supportsResultSetMetadataRetrievalOnly());
   assertFalse(nativeMeta.isSystemTable("FOO"));
   assertTrue(nativeMeta.supportsNewLinesInSQL());
   assertNull(nativeMeta.getSQLListOfSchemas());
   assertEquals(0, nativeMeta.getMaxColumnsInIndex());
   assertTrue(nativeMeta.supportsErrorHandlingOnBatchUpdates());
   assertTrue(nativeMeta.isExplorable());
   assertNull(nativeMeta.getXulOverlayFile());
   assertTrue(nativeMeta.onlySpaces("   \t   \n  \r   "));
   assertFalse(nativeMeta.isMySQLVariant());
   assertTrue(nativeMeta.canTest());
   assertTrue(nativeMeta.requiresName());
   assertTrue(nativeMeta.releaseSavepoint());
   Variables v = new Variables();
   v.setVariable("FOOVARIABLE", "FOOVALUE");
   DatabaseMeta dm = new DatabaseMeta();
   dm.setDatabaseInterface(nativeMeta);
   assertEquals("", nativeMeta.getDataTablespaceDDL(v, dm));
   assertEquals("", nativeMeta.getIndexTablespaceDDL(v, dm));
   assertFalse(nativeMeta.useSafePoints());
   assertTrue(nativeMeta.supportsErrorHandling());
   assertEquals("'DATA'", nativeMeta.getSQLValue(new ValueMetaString("FOO"), "DATA", null));
   assertEquals("'15'", nativeMeta.getSQLValue(new ValueMetaString("FOO"), "15", null));
   assertEquals("_", nativeMeta.getFieldnameProtector());
   assertEquals("_1ABC_123", nativeMeta.getSafeFieldname("1ABC 123"));
   BaseDatabaseMeta tmpSC =
       new ConcreteBaseDatabaseMeta() {
         @Override
         public String[] getReservedWords() {
           return new String[] {"SELECT"};
         }
       };
   assertEquals("SELECT_", tmpSC.getSafeFieldname("SELECT"));
   assertEquals("NOMAXVALUE", nativeMeta.getSequenceNoMaxValueOption());
   assertTrue(nativeMeta.supportsAutoGeneratedKeys());
   assertNull(nativeMeta.customizeValueFromSQLType(new ValueMetaString("FOO"), null, 0));
   assertTrue(nativeMeta.fullExceptionLog(new RuntimeException("xxxx")));
 }
 @Test
 public void testGettersSetters() {
   // Note - this method should *ONLY* use the jndi meta and not the odbc or native ones.
   // This is the only method in this test class that mutates the meta.
   jndiMeta.setUsername("FOO");
   assertEquals("FOO", jndiMeta.getUsername());
   jndiMeta.setPassword("BAR");
   assertEquals("BAR", jndiMeta.getPassword());
   jndiMeta.setAccessType(DatabaseMeta.TYPE_ACCESS_JNDI);
   assertEquals("", jndiMeta.getUsername());
   assertEquals("", jndiMeta.getPassword());
   assertFalse(jndiMeta.isChanged());
   jndiMeta.setChanged(true);
   assertTrue(jndiMeta.isChanged());
   jndiMeta.setName("FOO");
   assertEquals("FOO", jndiMeta.getName());
   assertEquals("FOO", jndiMeta.getDisplayName());
   jndiMeta.setName(null);
   assertNull(jndiMeta.getName());
   assertEquals("FOO", jndiMeta.getDisplayName());
   jndiMeta.setDisplayName(null);
   assertNull(jndiMeta.getDisplayName());
   jndiMeta.setDatabaseName("FOO");
   assertEquals("FOO", jndiMeta.getDatabaseName());
   assertEquals("-1", jndiMeta.getDatabasePortNumberString());
   jndiMeta.setDatabasePortNumberString("9876");
   assertEquals("9876", jndiMeta.getDatabasePortNumberString());
   jndiMeta.setDatabasePortNumberString(null);
   assertEquals(
       "9876", jndiMeta.getDatabasePortNumberString()); // not sure I agree with this behavior
   jndiMeta.setHostname("FOO");
   assertEquals("FOO", jndiMeta.getHostname());
   LongObjectId id = new LongObjectId(9876);
   jndiMeta.setObjectId(id);
   assertEquals(id, jndiMeta.getObjectId());
   jndiMeta.setServername("FOO");
   assertEquals("FOO", jndiMeta.getServername());
   jndiMeta.setDataTablespace("FOO");
   assertEquals("FOO", jndiMeta.getDataTablespace());
   jndiMeta.setIndexTablespace("FOO");
   assertEquals("FOO", jndiMeta.getIndexTablespace());
   Properties attrs = jndiMeta.getAttributes();
   Properties testAttrs = new Properties();
   testAttrs.setProperty("FOO", "BAR");
   jndiMeta.setAttributes(testAttrs);
   assertEquals(testAttrs, jndiMeta.getAttributes());
   jndiMeta.setAttributes(attrs); // reset attributes back to what they were...
   jndiMeta.setSupportsBooleanDataType(true);
   assertTrue(jndiMeta.supportsBooleanDataType());
   jndiMeta.setSupportsTimestampDataType(true);
   assertTrue(jndiMeta.supportsTimestampDataType());
   jndiMeta.setPreserveReservedCase(false);
   assertFalse(jndiMeta.preserveReservedCase());
   jndiMeta.addExtraOption("JNDI", "FOO", "BAR");
   Map<String, String> expectedOptionsMap = new HashMap<String, String>();
   expectedOptionsMap.put("JNDI.FOO", "BAR");
   assertEquals(expectedOptionsMap, jndiMeta.getExtraOptions());
   jndiMeta.setConnectSQL("SELECT COUNT(*) FROM FOO");
   assertEquals("SELECT COUNT(*) FROM FOO", jndiMeta.getConnectSQL());
   jndiMeta.setUsingConnectionPool(true);
   assertTrue(jndiMeta.isUsingConnectionPool());
   jndiMeta.setMaximumPoolSize(15);
   assertEquals(15, jndiMeta.getMaximumPoolSize());
   jndiMeta.setInitialPoolSize(5);
   assertEquals(5, jndiMeta.getInitialPoolSize());
   jndiMeta.setPartitioned(true);
   assertTrue(jndiMeta.isPartitioned());
   PartitionDatabaseMeta[] clusterInfo = new PartitionDatabaseMeta[1];
   PartitionDatabaseMeta aClusterDef = new PartitionDatabaseMeta("FOO", "BAR", "WIBBLE", "NATTIE");
   aClusterDef.setUsername("FOOUSER");
   aClusterDef.setPassword("BARPASSWORD");
   clusterInfo[0] = aClusterDef;
   jndiMeta.setPartitioningInformation(clusterInfo);
   PartitionDatabaseMeta[] gotPartitions = jndiMeta.getPartitioningInformation();
   // MB: Can't use arrayEquals because the PartitionDatabaseMeta doesn't have a toString. :(
   // assertArrayEquals( clusterInfo, gotPartitions );
   assertTrue(gotPartitions != null);
   if (gotPartitions != null) {
     assertEquals(1, gotPartitions.length);
     PartitionDatabaseMeta compareWith = gotPartitions[0];
     // MB: Can't use x.equals(y) because PartitionDatabaseMeta doesn't override equals... :(
     assertEquals(aClusterDef.getClass(), compareWith.getClass());
     assertEquals(aClusterDef.getDatabaseName(), compareWith.getDatabaseName());
     assertEquals(aClusterDef.getHostname(), compareWith.getHostname());
     assertEquals(aClusterDef.getPartitionId(), compareWith.getPartitionId());
     assertEquals(aClusterDef.getPassword(), compareWith.getPassword());
     assertEquals(aClusterDef.getPort(), compareWith.getPort());
     assertEquals(aClusterDef.getUsername(), compareWith.getUsername());
   }
   Properties poolProperties = new Properties();
   poolProperties.put("FOO", "BAR");
   poolProperties.put("BAR", "FOO");
   poolProperties.put("ZZZZZZZZZZZZZZ", "Z.Z.Z.Z.Z.Z.Z.Z.a.a.a.a.a.a.a.a.a");
   poolProperties.put("TOM", "JANE");
   poolProperties.put("AAAAAAAAAAAAA", "BBBBB.BBB.BBBBBBB.BBBBBBBB.BBBBBBBBBBBBBB");
   jndiMeta.setConnectionPoolingProperties(poolProperties);
   Properties compareWithProps = jndiMeta.getConnectionPoolingProperties();
   assertEquals(poolProperties, compareWithProps);
   jndiMeta.setStreamingResults(false);
   assertFalse(jndiMeta.isStreamingResults());
   jndiMeta.setQuoteAllFields(true);
   jndiMeta.setForcingIdentifiersToLowerCase(true);
   jndiMeta.setForcingIdentifiersToUpperCase(true);
   assertTrue(jndiMeta.isQuoteAllFields());
   assertTrue(jndiMeta.isForcingIdentifiersToLowerCase());
   assertTrue(jndiMeta.isForcingIdentifiersToUpperCase());
   jndiMeta.setUsingDoubleDecimalAsSchemaTableSeparator(true);
   assertTrue(jndiMeta.isUsingDoubleDecimalAsSchemaTableSeparator());
   jndiMeta.setPreferredSchemaName("FOO");
   assertEquals("FOO", jndiMeta.getPreferredSchemaName());
 }
 @Test
 public void testDefaultSQLStatements() {
   // Note - this method should use only native or odbc metas.
   // Use of the jndi meta here could create a race condition
   // when test cases are run by multiple threads
   String lineSep = System.getProperty("line.separator");
   String expected = "ALTER TABLE FOO DROP BAR" + lineSep;
   assertEquals(
       expected,
       odbcMeta.getDropColumnStatement("FOO", new ValueMetaString("BAR"), "", false, "", false));
   assertEquals("TRUNCATE TABLE FOO", odbcMeta.getTruncateTableStatement("FOO"));
   assertEquals("SELECT * FROM FOO", odbcMeta.getSQLQueryFields("FOO"));
   assertEquals("SELECT 1 FROM FOO", odbcMeta.getSQLTableExists("FOO"));
   assertEquals("SELECT FOO FROM BAR", odbcMeta.getSQLColumnExists("FOO", "BAR"));
   assertEquals(
       "insert into \"FOO\".\"BAR\"(KEYFIELD, VERSIONFIELD) values (0, 1)",
       nativeMeta.getSQLInsertAutoIncUnknownDimensionRow(
           "\"FOO\".\"BAR\"", "KEYFIELD", "VERSIONFIELD"));
   assertEquals("select count(*) FROM FOO", nativeMeta.getSelectCountStatement("FOO"));
   assertEquals("COL9", nativeMeta.generateColumnAlias(9, "FOO"));
   assertEquals(
       "[SELECT 1, INSERT INTO FOO VALUES(BAR), DELETE FROM BAR]",
       nativeMeta
           .parseStatements("SELECT 1;INSERT INTO FOO VALUES(BAR);DELETE FROM BAR")
           .toString());
   assertEquals("CREATE TABLE ", nativeMeta.getCreateTableStatement());
   assertEquals("DROP TABLE IF EXISTS FOO", nativeMeta.getDropTableIfExistsStatement("FOO"));
 }