All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.client.VersionIT Maven / Gradle / Ivy

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package net.snowflake.client;

import net.snowflake.client.loader.Loader;
import net.snowflake.client.loader.LoaderFactory;
import net.snowflake.client.loader.LoaderProperty;
import net.snowflake.client.loader.StreamLoader;
import net.snowflake.client.loader.Operation;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;



/**
 *
 * @author dengovatov
 */
public class VersionIT
{

  // test DB
  static String DB = "DB", DBC = "DBC";
  
  // test schemas
  static String SC = "SC", SCC = "SCC";
  
  // test tables
  static String T = "T", T2 = "T2", TC = "TC";
  
  // Before creation
  static Long check1, check2, check3, check4, check5, check6, check7, check8;
    
  
  /**
   * Timeline
   * 
   * check1
   * 
   * DB, SC, DB.SC.T created
   * T populated with one row
   * 
   * check 2
   * 
   * T modified an extra 5000001 rows
   * 
   * check 3
   * 
   * T2 created as a clone of T prior to check 2
   * validate 1 row in T2
   * 
   * check 4
   * 
   * T2 modified, insert content of T
   * validate 5000002 rows
   * T is dropped
   * 
   * check 5
   * 
   * TC is created as clone of T2 before checkpoint 4
   * validate 1 row in TC
   * 
   * check 6
   * 
   * SCC created as clone of SC prior to checkpoint 4
   * validate T and T2 present, 5000001 rows in T, 1 in T2
   * validate TC not present
   * 
   * check 7
   * 
   * undrop DB.SC.T
   * drop DB.SCC.T2
   * 
   * check 8
   * 
   * validate DB
   * 
   * create DBC as clone of DB prior to checkpoint 8
   * validate DBC.SC.T exists, 5000001 rows
   * validate DBC.SC.T2 exists, 5000002 rows
   * validate DBC.SC.TC exists, 1 row
   * validate DBC.SCC.T exists, 5000001 rows
   * validate DBC.SCC.TC does not exist
   */
  
  
  static Connection testConnection;
  static Connection putConnection;


  public VersionIT()
  {
  }

  @BeforeClass
  public static void setUpClass() throws Throwable
  {

    String accountStr = "testaccount";

    if (System.getenv("SF_ACCOUNT") != null)
    {
      accountStr = System.getenv("SF_ACCOUNT");
    }

    // create a new connection
    String connectionUrl = System.getenv("SF_JDBC_CONNECT_STRING");

    // use the default connection string if it is not set in environment
    if (connectionUrl == null)
    {
      connectionUrl = "jdbc:snowflake://localhost:8080";
    }

    connectionUrl = connectionUrl + "/?account=" + accountStr + "&user=snowman&password=test&schema=testschema&db=testdb";

    Properties properties = new Properties();
    properties.put("internal", "true");
    properties.put("ssl", "off");

    testConnection = DriverManager.getConnection(connectionUrl, properties);
    putConnection = DriverManager.getConnection(connectionUrl, properties);

    check1 = getTime();
    
    testConnection.createStatement().execute(
            "DROP DATABASE IF EXISTS DB");
    testConnection.createStatement().execute(
            "DROP DATABASE IF EXISTS DBC");
    testConnection.createStatement().execute(
            "CREATE DATABASE DB");
    testConnection.createStatement().execute(
            "CREATE SCHEMA SC");
    testConnection.createStatement().execute(
            "USE SCHEMA SC");
    putConnection.createStatement().execute(
            "USE DATABASE DB");    
    putConnection.createStatement().execute(
            "USE SCHEMA SC");    
    testConnection.createStatement().execute(
            "CREATE TABLE DB.SC.T(S VARCHAR, T timestamp)");
    testConnection.createStatement().execute(
            "insert into DB.SC.T values('blah', 0::timestamp)");
            
    
    
    check2 = getTime();
    
    //Insert data into T
    testConnection.createStatement().execute(
            "CREATE OR REPLACE STAGE loadertest URL='file:///tmp/loadertest'");

    Map prop = new HashMap<>();
    prop.put(LoaderProperty.tableName, "T");
    prop.put(LoaderProperty.schemaName, "SC");
    prop.put(LoaderProperty.databaseName, "DB");
    prop.put(LoaderProperty.remoteStage, "loadertest");
    prop.put(LoaderProperty.operation, Operation.INSERT);
    prop.put(LoaderProperty.columns, Arrays.asList(new String[]{"S", "T"}));
    
    Loader sl = LoaderFactory.createLoader(prop, putConnection, testConnection);
    sl.start();
  
    // INSERT
    Random rnd = new Random();

    long ct = System.nanoTime();
    
    for (int i = 0; i < 5000000; i++)
    {
      Object[] row = new Object[]
      {
        String.valueOf("{\"foo_" + i + "\":" + rnd + "}"), new Date()
      };
      sl.submitRow(row);
    }

    sl.finish();
    
    System.out.println(String.valueOf((long)((System.nanoTime() - ct)/200000.0)) + " rows/sec");
    testConnection.createStatement().execute("DROP STAGE loadertest");



  }

  @AfterClass
  public static void tearDownClass() throws SQLException
  {
    testConnection.createStatement().execute(
            "DROP DATABASE IF EXISTS DB");
    testConnection.createStatement().execute(
            "DROP DATABASE IF EXISTS DBC");
    testConnection.close();
    putConnection.close();
  }

  @Before
  public void setUp()
  {
  }

  @After
  public void tearDown()
  {
  }

  @Test
  public void testClone() throws Exception
  {
    // after check point 2
    assertEquals(5000001, countRows("DB.SC.T"));
    assertEquals(1, countRows("DB.SC.T", check2));
        
    check3 = getTime();
    
    run("CREATE TABLE T2 CLONE DB.SC.T" + before(check2));
    
    assertEquals(1, countRows("DB.SC.T2"));
    
    check4 = getTime();
    
    run("INSERT INTO T2 SELECT * FROM T");
    assertEquals(5000002, countRows("DB.SC.T2"));
    run("DROP TABLE T");
    assertEquals(-1, countRows("DB.SC.T"));
    
    check5 = getTime();
    
    run("CREATE TABLE TC CLONE DB.SC.T2" + before(check4));
    assertEquals(1, countRows("DB.SC.TC"));
    
    check6 = getTime();
    
    run("CREATE SCHEMA SCC CLONE SC" + before(check4));
    assertEquals(1, countRows("DB.SCC.T2"));
    assertEquals(5000001, countRows("DB.SCC.T"));
    assertEquals(-1, countRows("DB.SCC.TC"));
    
    check7 = getTime();
    
    assertEquals(-1, countRows("DB.SC.T"));
    run("USE SCHEMA SC");
    run("UNDROP TABLE T");
    run("DROP TABLE DB.SCC.T2");
    
    check8 = getTime();
    
    run("CREATE DATABASE DBC CLONE DB" + before(check8));
    assertEquals(5000001, countRows("DBC.SC.T"));
    assertEquals(5000002, countRows("DBC.SC.T2"));
    assertEquals(1, countRows("DBC.SC.TC"));
    assertEquals(5000001, countRows("DBC.SCC.T"));
    assertEquals(-1, countRows("DBC.SCC.T2"));
    assertEquals(-1, countRows("DBC.SCC.TC"));

    
  }

  /**
   * Return current epoch time
   */
  private static long getTime() throws Exception
  {

    Thread.sleep(1100);  // longer sleep
    ResultSet rs
              = testConnection.createStatement().executeQuery(
                    "select extract(epoch_millisecond from current_timestamp()) as N from dual");
    rs.next();
    long time =  rs.getLong("N");
    
    return time;
  }

  /**
   * Return -1 for table not present
   */
  private static long countRows(String table)
  {
    return countRows(table, null);
  }
  
  private static long countRows(String table, Long time)
  {
    
    try
    {
      
      String query = "select count(*) as count from "
              + table;
      
      if(time != null)
      {
        query = query + before(time);
      }
      
      ResultSet rs
      = testConnection.createStatement().executeQuery(query);
      rs.next();
      return rs.getLong("COUNT");
    }
    catch (SQLException ex)
    {
       return -1L;
    }
  }
  
  
  private static void run(String query) throws SQLException
  {
    testConnection.createStatement().execute(query);
  }
  
  
  private static String before(long time)
  {
    
    long seconds = time / 1000;
    long millis = time % 1000;
    String stamp = seconds + "." + millis;
    
    return " BEFORE(TIMESTAMP => TO_TIMESTAMP(" + stamp + "))";
  }
  
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy