[teiid-commits] teiid SVN: r4396 - in trunk: client/src/main/java/org/teiid and 5 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Tue Sep 4 08:26:59 EDT 2012
Author: shawkins
Date: 2012-09-04 08:26:59 -0400 (Tue, 04 Sep 2012)
New Revision: 4396
Removed:
trunk/client/src/main/java/org/teiid/adminapi/
Modified:
trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
trunk/client/src/main/java/org/teiid/client/BatchSerializer.java
trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java
trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties
trunk/client/src/test/java/org/teiid/client/TestBatchSerializer.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
Log:
TEIID-2175 changing the date/time serialization
Modified: trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/build/kits/jboss-as7/docs/teiid/teiid-releasenotes.html 2012-09-04 12:26:59 UTC (rev 4396)
@@ -42,9 +42,11 @@
<li>decodeinteger/decodestring have been deprecated. A CASE expression should be used instead.
</ul>
-<h4>from 8.0</h4>
+<h4>from 8.1</h4>
<ul>
<li>TEIID-2166 array_get will return null if the index is out of bounds rather than raising an error.
+ <li>TEIID-2175 for 8.0 and 8.1 clients the server will check if serialized date/time values fall outside of 32-bit value ranges (year 1900 - 9999 for dates and times between years 1901 and 2038) and throw an exception. The previous behavior was
+ to truncate. The exception and the use of 32 bit serialization can be avoided by setting the system property org.teiid.longDatesTimes to true.
</ul>
<h4>from 8.0</h4>
Modified: trunk/client/src/main/java/org/teiid/client/BatchSerializer.java
===================================================================
--- trunk/client/src/main/java/org/teiid/client/BatchSerializer.java 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/client/src/main/java/org/teiid/client/BatchSerializer.java 2012-09-04 12:26:59 UTC (rev 4396)
@@ -54,10 +54,20 @@
/**
* @since 4.2
+ *
+ * <ul>
+ * <li>version 0: starts with 7.1 and uses simple serialization too broadly
+ * <li>version 1: starts with 8.0 uses better string, blob, clob, xml, etc.
+ * add varbinary support.
+ * however was possibly silently truncating date/time values that were
+ * outside of jdbc allowed values
+ * <li>version 2: starts with 8.2 and adds better array serialization and
+ * uses a safer date/time serialization
+ * </ul>
*/
public class BatchSerializer {
- private static final byte CURRENT_VERSION = (byte)2;
+ static final byte CURRENT_VERSION = (byte)2;
private BatchSerializer() {} // Uninstantiable
@@ -70,13 +80,13 @@
serializers.put(DataTypeManager.DefaultDataTypes.BOOLEAN, new ColumnSerializer[] {new BooleanColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.BYTE, new ColumnSerializer[] {new ByteColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.CHAR, new ColumnSerializer[] {new CharColumnSerializer()});
- serializers.put(DataTypeManager.DefaultDataTypes.DATE, new ColumnSerializer[] {new DateColumnSerializer(), new DateColumnSerializer1()});
+ serializers.put(DataTypeManager.DefaultDataTypes.DATE, new ColumnSerializer[] {new DateColumnSerializer(), new DateColumnSerializer1(), new DateColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.DOUBLE, new ColumnSerializer[] {new DoubleColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.FLOAT, new ColumnSerializer[] {new FloatColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.INTEGER, new ColumnSerializer[] {new IntColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.LONG, new ColumnSerializer[] {new LongColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.SHORT, new ColumnSerializer[] {new ShortColumnSerializer()});
- serializers.put(DataTypeManager.DefaultDataTypes.TIME, new ColumnSerializer[] {new TimeColumnSerializer(), new TimeColumnSerializer1()});
+ serializers.put(DataTypeManager.DefaultDataTypes.TIME, new ColumnSerializer[] {new TimeColumnSerializer(), new TimeColumnSerializer1(), new TimeColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.TIMESTAMP, new ColumnSerializer[] {new TimestampColumnSerializer()});
serializers.put(DataTypeManager.DefaultDataTypes.STRING, new ColumnSerializer[] {defaultSerializer, new StringColumnSerializer1()});
serializers.put(DataTypeManager.DefaultDataTypes.CLOB, new ColumnSerializer[] {defaultSerializer, new ClobColumnSerializer1()});
@@ -617,18 +627,30 @@
}
static int DATE_NORMALIZER = 0;
+ public final static long MIN_DATE_32;
+ public final static long MAX_DATE_32;
+ public final static long MIN_TIME_32;
+ public final static long MAX_TIME_32;
static {
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$
c.set(1900, 0, 1, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
- DATE_NORMALIZER = -(int)(c.getTime().getTime()/60000); //support a 32 bit range starting at this value
+ MIN_DATE_32 = c.getTimeInMillis();
+ MAX_DATE_32 = MIN_DATE_32 + ((1l<<32)-1)*60000;
+ DATE_NORMALIZER = -(int)(MIN_DATE_32/60000); //support a 32 bit range starting at this value
+ MAX_TIME_32 = Integer.MAX_VALUE*1000l;
+ MIN_TIME_32 = Integer.MIN_VALUE*1000l;
}
private static class DateColumnSerializer1 extends ColumnSerializer {
protected void writeObject(ObjectOutput out, Object obj) throws IOException {
- out.writeInt((int)(((java.sql.Date)obj).getTime()/60000) + DATE_NORMALIZER);
+ long time = ((java.sql.Date)obj).getTime();
+ if (time < MIN_DATE_32 || time > MAX_DATE_32) {
+ throw new IOException(JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID20029, obj.getClass().getName()));
+ }
+ out.writeInt((int)(time/60000) + DATE_NORMALIZER);
}
protected Object readObject(ObjectInput in) throws IOException {
return new java.sql.Date(((in.readInt()&0xffffffffL) - DATE_NORMALIZER)*60000);
@@ -637,7 +659,11 @@
private static class TimeColumnSerializer1 extends ColumnSerializer {
protected void writeObject(ObjectOutput out, Object obj) throws IOException {
- out.writeInt((int)(((Time)obj).getTime()/1000));
+ long time = ((Time)obj).getTime();
+ if (time < MIN_TIME_32 || time > MAX_TIME_32) {
+ throw new IOException(JDBCPlugin.Util.gs(JDBCPlugin.Event.TEIID20029, obj.getClass().getName()));
+ }
+ out.writeInt((int)(time/1000));
}
protected Object readObject(ObjectInput in) throws IOException {
return new Time((in.readInt()&0xffffffffL)*1000);
Modified: trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java
===================================================================
--- trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/client/src/main/java/org/teiid/jdbc/JDBCPlugin.java 2012-09-04 12:26:59 UTC (rev 4396)
@@ -57,6 +57,7 @@
TEIID20021,
TEIID20023,
TEIID20027,
- TEIID20028
+ TEIID20028,
+ TEIID20029
}
}
Modified: trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties
===================================================================
--- trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/client/src/main/resources/org/teiid/jdbc/i18n.properties 2012-09-04 12:26:59 UTC (rev 4396)
@@ -172,4 +172,5 @@
TEIID20028=data length too big: {0} > max of {1}. You may need to adjust the maxObjectSize client setting.
unexpected_element=Unexpected Element {0} encountered, expecting one of {1}
ambigious_gss_selection=Either configure "java.security.krb5.conf" property or combination of "java.security.krb5.realm" and "java.security.krb5.kdc" properties. Not both.
-no_gss_selection=No KRB5 configuration found. Either configure "java.security.krb5.conf" property or combination of "java.security.krb5.realm" and "java.security.krb5.kdc" properties.
\ No newline at end of file
+no_gss_selection=No KRB5 configuration found. Either configure "java.security.krb5.conf" property or combination of "java.security.krb5.realm" and "java.security.krb5.kdc" properties.
+TEIID20029={0} value outside of 32-bit value range. Please set the system property org.teiid.longDatesTimes to true to avoid this error.
\ No newline at end of file
Modified: trunk/client/src/test/java/org/teiid/client/TestBatchSerializer.java
===================================================================
--- trunk/client/src/test/java/org/teiid/client/TestBatchSerializer.java 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/client/src/test/java/org/teiid/client/TestBatchSerializer.java 2012-09-04 12:26:59 UTC (rev 4396)
@@ -38,6 +38,7 @@
import org.teiid.core.types.BinaryType;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.TimestampWithTimezone;
+import org.teiid.query.unittest.TimestampUtil;
/**
@@ -45,11 +46,12 @@
*/
public class TestBatchSerializer {
- private static void helpTestSerialization(String[] types, List<?>[] batch) throws IOException, ClassNotFoundException {
+ private static void helpTestSerialization(String[] types, List<?>[] batch, byte version) throws IOException, ClassNotFoundException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteStream);
List<List<?>> batchList = Arrays.asList(batch);
- BatchSerializer.writeBatch(out, types, batchList);
+
+ BatchSerializer.writeBatch(out, types, batchList, version);
out.flush();
byte[] bytes = byteStream.toByteArray();
@@ -119,28 +121,33 @@
@Test public void testSerializeBasicTypes() throws Exception {
// The number 8 is important here because boolean isNull information is packed into bytes,
// so we want to make sure the boundary cases are handled correctly
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(1)); // Less than 8 rows
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(8)); // Exactly 8 rows
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(17)); // More than 8 rows, but not a multiple of 8
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(120)); // A multiple of 8 rows
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(833)); // A bunch of rows. This should also test large strings
- helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(4096)); // A bunch of rows. This should also test large strings
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(1), BatchSerializer.CURRENT_VERSION); // Less than 8 rows
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(8), BatchSerializer.CURRENT_VERSION); // Exactly 8 rows
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(17), BatchSerializer.CURRENT_VERSION); // More than 8 rows, but not a multiple of 8
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(120), BatchSerializer.CURRENT_VERSION); // A multiple of 8 rows
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(833), BatchSerializer.CURRENT_VERSION); // A bunch of rows. This should also test large strings
+ helpTestSerialization(sampleBatchTypes, sampleBatchWithNulls(4096), BatchSerializer.CURRENT_VERSION); // A bunch of rows. This should also test large strings
}
@Test public void testSerializeLargeStrings() throws Exception {
List<?> row = Arrays.asList(new Object[] {sampleString(66666)});
- helpTestSerialization(new String[] {DataTypeManager.DefaultDataTypes.STRING}, new List[] {row});
+ helpTestSerialization(new String[] {DataTypeManager.DefaultDataTypes.STRING}, new List[] {row}, BatchSerializer.CURRENT_VERSION);
}
@Test public void testSerializeNoData() throws Exception {
- helpTestSerialization(sampleBatchTypes, new List[0]);
+ helpTestSerialization(sampleBatchTypes, new List[0], BatchSerializer.CURRENT_VERSION);
}
@Test public void testSerializeDatatypeMismatch() throws Exception {
try {
- helpTestSerialization(new String[] {DataTypeManager.DefaultDataTypes.DOUBLE}, new List[] {Arrays.asList(new Object[] {"Hello!"})}); //$NON-NLS-1$
+ helpTestSerialization(new String[] {DataTypeManager.DefaultDataTypes.DOUBLE}, new List[] {Arrays.asList(new Object[] {"Hello!"})}, BatchSerializer.CURRENT_VERSION); //$NON-NLS-1$
} catch (RuntimeException e) {
assertEquals("TEIID20001 The modeled datatype double for column 0 doesn't match the runtime type \"java.lang.String\". Please ensure that the column's modeled datatype matches the expected data.", e.getMessage()); //$NON-NLS-1$
}
}
+
+ @Test(expected=IOException.class) public void testOutOfRangeDate() throws Exception {
+ helpTestSerialization(new String[] {DataTypeManager.DefaultDataTypes.DATE}, new List[] {Arrays.asList(TimestampUtil.createDate(-2, 0, 1))}, (byte)1);
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java 2012-09-04 11:53:12 UTC (rev 4395)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPWorkContext.java 2012-09-04 12:26:59 UTC (rev 4396)
@@ -42,6 +42,7 @@
import org.teiid.adminapi.impl.SessionMetadata;
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.client.security.SessionToken;
+import org.teiid.core.util.PropertiesUtils;
import org.teiid.dqp.message.RequestID;
import org.teiid.security.SecurityHelper;
@@ -50,14 +51,13 @@
private static final long serialVersionUID = -6389893410233192977L;
+ private static final boolean longDatesTimes = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.longDatesTimes", false); //$NON-NLS-1$
+
public enum Version {
SEVEN_1("7.1", (byte)0), //$NON-NLS-1$
- SEVEN_2("7.2", (byte)0), //$NON-NLS-1$
SEVEN_3("7.3", (byte)0), //$NON-NLS-1$
SEVEN_4("7.4", (byte)0), //$NON-NLS-1$
- SEVEN_5("7.5", (byte)0), //$NON-NLS-1$
- SEVEN_6("7.6", (byte)0), //$NON-NLS-1$
- EIGHT_0("8.0", (byte)1), //$NON-NLS-1$
+ EIGHT_0("8.0", (byte)(longDatesTimes?0:1)), //$NON-NLS-1$
EIGHT_2("8.2", (byte)2); //$NON-NLS-1$
private String string;
More information about the teiid-commits
mailing list