Uploaded image for project: 'Teiid'
  1. Teiid
  2. TEIID-1933

0 size CLOBs in teiid cause unexpected problems

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 7.7
    • 7.6
    • None
    • None

      Hi,

      this issue is similar to the issue in TEIID-1927, but this time, we are experiencing similar problems when other code is inadvertently calling getSubString on 0 sized CLOB objects from teiid

      An example is below that takes some data from teiid and tries to put it into a mysql database

      import java.sql.Connection;
      import java.sql.DriverManager;
      import java.sql.PreparedStatement;
      import java.sql.ResultSet;
      import java.sql.ResultSetMetaData;
      import java.sql.SQLException;
      import java.sql.Statement;
      import java.util.ArrayList;
      import java.util.Iterator;
      
      import org.teiid.jdbc.TeiidDataSource;
      
      public class TestMain {
      	private static final String host = "vdb.example.com";
      	private static final String port = "31000";
      	private static final String vdb = "EngVDBR";
      	private static final String user = "user";
      	private static final String password = "user";
      
      	private static final int batchSize = 50000;
      
      	public static void main(String[] args) throws Exception {
      		new TestMain();
      	}
      	
      	public TestMain() {
      		try {
      			System.out.println("Executing using the TeiidDriver");
      			Connection connSrc = getSrcConnection();
      			Connection connTar = getTarConnection();
      			ArrayList<String> batches = getBatches(getCount(connSrc, "Bugzilla.bugs", "1 = 1"));
      			System.out.println(batches.size());
      			Iterator<String> it = batches.iterator();
      			while (it.hasNext()) {
      				String str = "select keywords from Bugzilla.bugs order by bug_id "
      						+ it.next();
      				System.out.println(str);
      				execute(connSrc, str, connTar);
      			}
      		} catch (Exception e) {
      			e.printStackTrace();
      		}
      	}
      	
      	static Connection getSrcConnection() throws Exception {
      		String url = "jdbc:teiid:" + vdb + "@mms://" + host + ":" + port
      				+ ";showplan=on";
      		Class.forName("org.teiid.jdbc.TeiidDriver");
      		return DriverManager.getConnection(url, user, password);
      	}
      
      	static Connection getTarConnection() throws Exception {
      		String url = "jdbc:mysql://localhost:3306/test";
      		Class.forName("com.mysql.jdbc.Driver");
      		return DriverManager.getConnection(url, "test", "test");
      	}
      
      	static Connection getDataSourceConnection() throws Exception {
      		TeiidDataSource ds = new TeiidDataSource();
      		ds.setDatabaseName(vdb);
      		ds.setUser(user);
      		ds.setPassword(password);
      		ds.setServerName(host);
      		ds.setPortNumber(Integer.valueOf(port));
      
      		ds.setShowPlan("on");
      
      		return ds.getConnection();
      	}
      	
      	public static void execute(Connection connSrc, String sql,
      			Connection connTar) throws Exception {
      		try {
      			Statement statement = connSrc.createStatement(
      					ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
      			// statement.setFetchSize(5000);
      
      			ResultSet results = statement.executeQuery(sql);
      
      			ResultSetMetaData metadata = results.getMetaData();
      			int columns = metadata.getColumnCount();
      			connTar.setAutoCommit(false);
      			PreparedStatement ps = connTar
      					.prepareStatement("insert into bugs values("
      							+ getColStr(columns) + ")");
      			System.out.println("insert into bugs values(" + getColStr(columns)
      					+ ")");
      			for (int row = 1; results.next(); row++) {
      				for (int i = 1; i <= columns; i++) {
                                              // System.out.println(results.getObject(i));
      					ps.setObject(i, results.getObject(i));
      
      				}
      				ps.executeUpdate();
      			}
      			connTar.commit();
      			results.close();
      			statement.close();
      		} catch (SQLException e) {
      			e.printStackTrace();
      			System.exit(1);
      		} finally {
      			
      		}
      	}
      
      	public ArrayList<String> getBatches(int tabCnt) {
      		ArrayList<String> batches = new ArrayList<String>();
      		int batchLen = 0;
      		int init = 0;
      		int endNum = 0;
      		if (tabCnt % batchSize == 0) {
      			batchLen = tabCnt / batchSize;
      		} else {
      			batchLen = tabCnt / batchSize + 1;
      		}
      		for (int i = 0; i < batchLen; i++) {
      			batches.add(" limit " + init + ", " + batchSize);
      			endNum = init + batchSize;
      			init = endNum;
      		}
      		return batches;
      	}
      
      	public int getCount(Connection conn, String table, String condition) {
      		try {
      			Statement stmt = conn.createStatement();
      			ResultSet rs = stmt.executeQuery("select count(1) from "
      					+ table + " where " + condition);
      			if (rs.next()) {
      				return rs.getInt(1);
      			}
      		} catch (Exception e) {
      
      		}
      		return 0;
      	}
      
      	public static String getColStr(int columnCount) {
      		StringBuffer sb = new StringBuffer();
      		for (int i = 0; i < columnCount; i++) {
      			sb.append("?,");
      		}
      		String str = sb.toString();
      		return str.substring(0, str.length() - 1);
      	}
      }
      

      Which throws the following error

      Executing using the TeiidDriver
      13
      select keywords from Bugzilla.bugs order by bug_id  limit 0, 50000
      insert into bugs values(?)
      javax.sql.rowset.serial.SerialException: Invalid position in BLOB object set
      	at javax.sql.rowset.serial.SerialClob.getSubString(SerialClob.java:246)
      	at com.mysql.jdbc.PreparedStatement.setClob(PreparedStatement.java:3553)
      	at com.mysql.jdbc.PreparedStatement.setObject(PreparedStatement.java:3979)
      	at com.redhat.com.hss.etl.util.TestMain.execute(TestMain.java:93)
      	at com.redhat.com.hss.etl.util.TestMain.<init>(TestMain.java:40)
      	at com.redhat.com.hss.etl.util.TestMain.main(TestMain.java:25)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:616)
      	at org.apache.tools.ant.taskdefs.ExecuteJava.run(ExecuteJava.java:217)
      	at org.apache.tools.ant.taskdefs.ExecuteJava.execute(ExecuteJava.java:152)
      	at org.apache.tools.ant.taskdefs.Java.run(Java.java:764)
      	at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:218)
      	at org.apache.tools.ant.taskdefs.Java.executeJava(Java.java:132)
      	at org.apache.tools.ant.taskdefs.Java.execute(Java.java:105)
      	at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:616)
      	at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
      	at org.apache.tools.ant.Task.perform(Task.java:348)
      	at org.apache.tools.ant.Target.execute(Target.java:357)
      	at org.apache.tools.ant.Target.performTasks(Target.java:385)
      	at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1337)
      	at org.apache.tools.ant.Project.executeTarget(Project.java:1306)
      	at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
      	at org.apache.tools.ant.Project.executeTargets(Project.java:1189)
      	at org.apache.tools.ant.Main.runBuild(Main.java:758)
      	at org.apache.tools.ant.Main.startAnt(Main.java:217)
      	at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
      	at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
      

      On closer inspection it looks like inside the mysql driver it's calling getSubString(1, 0) on the object because the CLOB object is size 0, which is the problem in the first place.

              rhn-engineering-shawkins Steven Hawkins
              graeme.gillies Graeme Gillies (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Created:
                Updated:
                Resolved: