1 5 package org.h2.test.synth; 6 7 import java.math.BigDecimal ; 8 import java.sql.Date ; 9 import java.sql.ResultSet ; 10 import java.sql.ResultSetMetaData ; 11 import java.sql.SQLException ; 12 import java.sql.Time ; 13 import java.sql.Timestamp ; 14 import java.sql.Types ; 15 16 import org.h2.value.DataType; 17 18 public class Value { 19 private int type; 20 private Object data; 21 private TestSynth config; 22 23 private Value(TestSynth config, int type, Object data) { 24 this.config = config; 25 this.type = type; 26 this.data = data; 27 } 28 29 String getSQL() { 30 if(data == null) { 31 return "NULL"; 32 } 33 switch(type) { 34 case Types.DECIMAL: 35 case Types.NUMERIC: 36 case Types.BIGINT: 37 case Types.INTEGER: 38 case Types.DOUBLE: 39 case Types.REAL: 40 return data.toString(); 41 case Types.CLOB: 42 case Types.VARCHAR: 43 case Types.CHAR: 44 case Types.OTHER: 45 case Types.LONGVARCHAR: 46 return "'" + data.toString() + "'"; 47 case Types.BLOB: 48 case Types.BINARY: 49 case Types.VARBINARY: 50 case Types.LONGVARBINARY: 51 return getBlobSQL(); 52 case Types.DATE: 53 return getDateSQL((Date )data); 54 case Types.TIME: 55 return getTimeSQL((Time )data); 56 case Types.TIMESTAMP: 57 return getTimestampSQL((Timestamp )data); 58 case DataType.TYPE_BOOLEAN: 59 case Types.BIT: 60 return (String )data; 61 default: 62 throw new Error ("type="+type); 63 } 64 } 65 66 private static Date randomDate(TestSynth config) { 67 return config.random().randomDate(); 68 69 } 70 71 private static Double randomDouble(TestSynth config) { 72 return new Double (config.random().getInt(100)/10.); 73 } 74 75 private static Long randomLong(TestSynth config) { 76 return new Long (config.random().getInt(1000)); 77 } 78 79 private static Time randomTime(TestSynth config) { 80 return config.random().randomTime(); 81 } 82 83 private static Timestamp randomTimestamp(TestSynth config) { 84 return config.random().randomTimestamp(); 85 } 86 87 private String getTimestampSQL(Timestamp ts) { 88 String s = "'"+ts.toString()+"'"; 89 if(config.getMode() != TestSynth.HSQLDB) { 90 s = "TIMESTAMP " + s; 91 } 92 return s; 93 } 94 95 private String getDateSQL(Date date) { 96 String s = "'"+date.toString()+"'"; 97 if(config.getMode() != TestSynth.HSQLDB) { 98 s = "DATE " + s; 99 } 100 return s; 101 } 102 103 private String getTimeSQL(Time time) { 104 String s = "'"+time.toString()+"'"; 105 if(config.getMode() != TestSynth.HSQLDB) { 106 s = "TIME " + s; 107 } 108 return s; 109 } 110 111 private String getBlobSQL() { 112 byte[] bytes = (byte[]) data; 113 StringBuffer buff = new StringBuffer ("'"); 115 for(int i=0; i<bytes.length; i++) { 116 int c = bytes[i] & 0xff; 117 buff.append(Integer.toHexString(c >> 4 & 0xf)); 118 buff.append(Integer.toHexString(c & 0xf)); 119 120 } 121 buff.append("'"); 122 return buff.toString(); 123 } 124 125 public static Value read(TestSynth config, ResultSet rs, int index) throws SQLException { 126 ResultSetMetaData meta = rs.getMetaData(); 127 Object data; 128 int type = meta.getColumnType(index); 129 switch(type) { 130 case Types.REAL: 131 case Types.DOUBLE: 132 data = new Double (rs.getDouble(index)); 133 break; 134 case Types.BIGINT: 135 data = new Long (rs.getLong(index)); 136 break; 137 case Types.DECIMAL: 138 case Types.NUMERIC: 139 data = rs.getBigDecimal(index); 140 break; 141 case Types.BLOB: 142 case Types.BINARY: 143 case Types.VARBINARY: 144 case Types.LONGVARBINARY: 145 data = rs.getBytes(index); 146 break; 147 case Types.OTHER: 148 case Types.CLOB: 149 case Types.VARCHAR: 150 case Types.LONGVARCHAR: 151 case Types.CHAR: 152 data = rs.getString(index); 153 break; 154 case Types.DATE: 155 data = rs.getDate(index); 156 break; 157 case Types.TIME: 158 data = rs.getTime(index); 159 break; 160 case Types.TIMESTAMP: 161 data = rs.getTimestamp(index); 162 break; 163 case Types.INTEGER: 164 data = new Integer (rs.getInt(index)); 165 break; 166 case Types.NULL: 167 data = null; 168 break; 169 case DataType.TYPE_BOOLEAN: 170 case Types.BIT: 171 data = rs.getBoolean(index) ? "TRUE" : "FALSE"; 172 break; 173 default: 174 throw new Error ("type="+type); 175 } 176 if(rs.wasNull()) { 177 data = null; 178 } 179 return new Value(config, type, data); 180 } 181 182 public static Value getRandom(TestSynth config, int type, int precision, int scale, boolean mayBeNull) { 183 Object data; 184 if(mayBeNull && config.random().getBoolean(20)) { 185 return new Value(config, type, null); 186 } 187 switch(type) { 188 case Types.BIGINT: 189 data = randomLong(config); 190 break; 191 case Types.DOUBLE: 192 data = randomDouble(config); 193 break; 194 case Types.DECIMAL: 195 data = randomDecimal(config, precision, scale); 196 break; 197 case Types.VARBINARY: 198 case Types.BINARY: 199 case Types.BLOB: 200 data = randomBytes(config, precision); 201 break; 202 case Types.CLOB: 203 case Types.VARCHAR: 204 data = config.random().randomString(config.random().getInt(precision)); 205 break; 206 case Types.DATE: 207 data = randomDate(config); 208 break; 209 case Types.TIME: 210 data = randomTime(config); 211 break; 212 case Types.TIMESTAMP: 213 data = randomTimestamp(config); 214 break; 215 case Types.INTEGER: 216 data = randomInt(config); 217 break; 218 case DataType.TYPE_BOOLEAN: 219 case Types.BIT: 220 data = config.random().getBoolean(50) ? "TRUE" : "FALSE"; 221 break; 222 default: 223 throw new Error ("type="+type); 224 } 225 return new Value(config, type, data); 226 } 227 228 private static Object randomInt(TestSynth config) { 229 int value; 230 if(config.is(TestSynth.POSTGRESQL)) { 231 value = config.random().getInt(1000000); 232 } else { 233 value = config.random().getRandomInt(); 234 } 235 return new Integer (value); 236 } 237 238 private static byte[] randomBytes(TestSynth config, int max) { 239 int len = config.random().getLog(max); 240 byte[] data = new byte[len]; 241 config.random().getBytes(data); 242 return data; 243 } 244 245 private static BigDecimal randomDecimal(TestSynth config, int precision, int scale) { 246 int len = config.random().getLog(precision-scale)+scale; 247 if(len==0) { 248 len++; 249 } 250 StringBuffer buff = new StringBuffer (); 251 for(int i=0; i<len; i++) { 252 buff.append((char) ('0' + config.random().getInt(10))); 253 } 254 buff.insert(len - scale, '.'); 255 if(config.random().getBoolean(20)) { 256 buff.insert(0, '-'); 257 } 258 return new BigDecimal (buff.toString()); 259 } 260 261 public int compareTo(Object o) { 262 Value v = (Value)o; 263 if(type != v.type) { 264 throw new Error ("compare "+type+" "+v.type+" "+data+" "+v.data); 265 } 266 if(data==null) { 267 return (v.data==null) ? 0 : -1; 268 } else if(v.data==null) { 269 return 1; 270 } 271 switch(type) { 272 case Types.DECIMAL: 273 return ((BigDecimal )data).compareTo((BigDecimal )v.data); 274 case Types.BLOB: 275 case Types.VARBINARY: 276 case Types.BINARY: 277 return compareBytes((byte[])data, (byte[])v.data); 278 case Types.CLOB: 279 case Types.VARCHAR: 280 return data.toString().compareTo(v.data.toString()); 281 case Types.DATE: 282 return ((Date )data).compareTo((Date )v.data); 283 case Types.INTEGER: 284 return ((Integer )data).compareTo((Integer )v.data); 285 default: 286 throw new Error ("type="+type); 287 } 288 } 289 290 static int compareBytes(byte[] a, byte[] b) { 291 int al = a.length, bl = b.length; 292 int len = Math.min(al, bl); 293 for(int i=0; i<len; i++) { 294 int x = a[i] & 0xff; 295 int y = b[i] & 0xff; 296 if(x==y) { 297 continue; 298 } 299 return x>y ? 1 : -1; 300 } 301 return al==bl ? 0 : al > bl ? 1 : -1; 302 } 303 304 public String toString() { 305 return getSQL(); 306 } 307 308 } 309 | Popular Tags |