Uploaded image for project: 'Calcite'
  1. Calcite
  2. CALCITE-1052

Phoenix queryserver sends result set in response to the wrong request when there are concurrent requests

VotersWatch issueWatchersLinkCloneUpdate Comment AuthorReplace String in CommentUpdate Comment VisibilityDelete Comments
    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Critical
    • Resolution: Cannot Reproduce
    • None
    • 1.7.0
    • avatica

    Description

      Create two tables

      DROP TABLE IF EXISTS SEN.VARCHAR_TABLE;
      CREATE TABLE IF NOT EXISTS SEN.VARCHAR_TABLE(
      	KeyColumn VARCHAR(255) PRIMARY KEY,
      	Column1 VARCHAR(510));
      
      UPSERT INTO SEN.VARCHAR_TABLE VALUES ('One','1');
      
      DROP TABLE IF EXISTS SEN.INTEGER_TABLE;
      CREATE TABLE IF NOT EXISTS SEN.INTEGER_TABLE(
      	KeyColumn VARCHAR(255) PRIMARY KEY,
      	Column1 INTEGER);
      
      UPSERT INTO SEN.INTEGER_TABLE VALUES ('Two',2);
      

      Running these two programs results in several crashes.

      1. select a varchar by parameterized statement resulting in
      SELECT Column1 FROM SEN.VARCHAR_TABLE WHERE KeyColumn = 'One'

      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.PreparedStatement;
      import java.sql.Statement;
      
      public class Hello_World {
      	public static void main(String[] args) throws SQLException {
      		try {
                  Class.forName("org.apache.phoenix.queryserver.client.Driver");
              } catch (ClassNotFoundException e) {
                  System.out.println("Where is your PhoenixDriver");
                  e.printStackTrace();
                  return;
              }
      
      		Connection conn = DriverManager.getConnection("jdbc:phoenix:thin:url=http://192.168.222.52:8765");
      		conn.setAutoCommit(true);
      
      		String sqlStmt = "SELECT Column1 FROM SEN.VARCHAR_TABLE WHERE KeyColumn = ?";
      		System.out.println("SQL Statement:\n\t" + sqlStmt);
      		
      		while(true)
      		{
      			ResultSet rset = null;
      	
      			//Statement stmt = conn.createStatement();
      			PreparedStatement stmt = conn.prepareStatement(sqlStmt);
      			stmt.setString(1, "One");
      			ResultSet rs = stmt.executeQuery();
            
      			while (rs.next()) {
      		    	String column1 = rs.getString("column1");
      		    	if (!column1.equals("1"))
      		    	{
      		    		System.out.println(column1);
      		    	}
      			}
      		}
      		
              //conn.close();
      	}
      	
      }
      

      2. select an integer by parameterized statement resulting in
      SELECT Column1 FROM SEN.INTEGER_TABLE WHERE KeyColumn = 'Two'

      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.PreparedStatement;
      import java.sql.Statement;
      
      
      
      public class Hello_World {
      	public static void main(String[] args) throws SQLException {
      		try {
                  Class.forName("org.apache.phoenix.queryserver.client.Driver");
              } catch (ClassNotFoundException e) {
                  System.out.println("Where is your PhoenixDriver");
                  e.printStackTrace();
                  return;
              }
      
      		Connection conn = DriverManager.getConnection("jdbc:phoenix:thin:url=http://192.168.222.52:8765");
      		conn.setAutoCommit(true);
      		
      		String sqlStmt = "SELECT Column1 FROM SEN.INTEGER_TABLE WHERE KeyColumn = ?";
      		System.out.println("SQL Statement:\n\t" + sqlStmt);
      		
      		while(true)
      		{
      			ResultSet rset = null;
      	
      			//Statement stmt = conn.createStatement();
      			PreparedStatement stmt = conn.prepareStatement(sqlStmt);
      			stmt.setString(1, "Two");
      			ResultSet rs = stmt.executeQuery();
            
      			while (rs.next()) {
      		    	int column1 = rs.getInt("column1");
      		    	if (column1 != 2)
      		    	{
      		    		System.out.println(column1);
      		    	}
      			}
      		}
      		
              //conn.close();
      	}
      	
      }
      
      

      There are several crashes (might be preventable by adding a pause in the loops?), but the one relevant to this bug is:

      SQL Statement:
      	SELECT Column1 FROM SEN.INTEGER_TABLE WHERE KeyColumn = ?
      Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Number
      	at org.apache.calcite.avatica.util.AbstractCursor$NumberAccessor.getNumber(AbstractCursor.java:661)
      	at org.apache.calcite.avatica.util.AbstractCursor$BigNumberAccessor.getInt(AbstractCursor.java:602)
      	at org.apache.calcite.avatica.AvaticaResultSet.getInt(AvaticaResultSet.java:314)
      	at Hello_World.main(Hello_World.java:36)
      
      

      where we get a string from SEN.VARCHAR_TABLE while we are querying from the SEN.INTEGER_TABLE.

      The queryserver is sending the result set in response to a request made from another connection id. The statement id was not checked but there may have been a statement id collision

      Attachments

        1. test.zip
          7 kB
          Kevin Liew
        2. phoenix-root-server.log
          10 kB
          Kevin Liew

        Activity

          This comment will be Viewable by All Users Viewable by All Users
          Cancel

          People

            elserj Josh Elser
            kliew Kevin Liew
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Slack

                Issue deployment