Quadcap Embeddable Database

com/quadcap/sql/types/Value.java

Go to the documentation of this file.
00001 package com.quadcap.sql.types; 00002 00003 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.ByteArrayInputStream; 00042 import java.io.ByteArrayOutputStream; 00043 import java.io.IOException; 00044 00045 import java.util.Hashtable; 00046 00047 import java.sql.SQLException; 00048 import java.sql.Types; 00049 00050 import com.quadcap.sql.file.Datafile; 00051 00052 import com.quadcap.sql.io.ObjectInputStream; 00053 import com.quadcap.sql.io.ObjectOutputStream; 00054 00055 import com.quadcap.util.Debug; 00056 00057 /** 00058 * A runtime SQL value. 00059 * 00060 * <p>Types: 00061 * <ul> 00062 * <li>Numeric 00063 * <li>Decimal 00064 * <li>Integer 00065 * <li>SmallInt 00066 * 00067 * <li>Float 00068 * <li>Double 00069 * 00070 * <li>Timestamp 00071 * <li>Interval 00072 * 00073 * <li>Char 00074 * 00075 * <li>Binary 00076 * 00077 * <li>Boolean 00078 * 00079 * <li>BLOB</li> 00080 * <li>CLOB</li> 00081 * </ul> 00082 * 00083 * @author Stan Bailes 00084 */ 00085 public abstract class Value { 00086 public Value() {} 00087 00088 public static boolean isCaseSensitive = true; 00089 00090 /** 00091 * Two-level virtual operator dispatch. Each subtype implements the 00092 * same basic template for this abstract function: 00093 * <pre> 00094 * 00095 * Value binop(int op, Value l) { 00096 * return l.binop(op, this); 00097 * } 00098 * 00099 * </pre> 00100 * Then, type overloading allows for each type to implement all 00101 * ops for which it can be the left hand side for all allowed types 00102 * on the right hand side: 00103 * Value binop(int op, ValueInteger l); 00104 * Value binop(int op, ValueLong l); 00105 * ... 00106 */ 00107 abstract public Value binop(int op, Value l) throws ValueException; 00108 00109 abstract public Object asJavaObject() throws SQLException; 00110 00111 abstract public Type getType() throws SQLException; 00112 00113 abstract public void fromJavaObject(Object obj) throws ValueException; 00114 00115 abstract public void serializeKey(KeyStream out) throws IOException; 00116 00117 public static String tn(Value v) { 00118 String s = v.getClass().getName(); 00119 int idx = s.lastIndexOf('.'); 00120 if (idx > 0) s = s.substring(idx+1); 00121 return s; 00122 } 00123 00124 public static final Value binop(int op, Value l, Value r) 00125 throws ValueException 00126 { 00127 Value ret = r.binop(op, l); 00128 // Debug.println("binop(" + Op.toString(op) + ", " + 00129 // tn(l) + ":" + 00130 // l + ", " + 00131 // tn(r) + ":" + 00132 // r + ") = " + 00133 // tn(ret) + ":" + 00134 // ret); 00135 return ret; 00136 } 00137 00138 final ValueException badType(Type type) { 00139 return new ValueException("Not " + type + ": " + 00140 this.getClass().getName()); 00141 } 00142 00143 // grep alltypes (also io.Extern) 00144 public Value convert(TypeBigInt type) throws ValueException { 00145 throw badType(type); 00146 } 00147 00148 public Value convert(TypeBinary type) throws ValueException { 00149 throw badType(type); 00150 } 00151 00152 public Value convert(TypeBlob type) throws ValueException { 00153 throw badType(type); 00154 } 00155 00156 public Value convert(TypeBoolean type) throws ValueException { 00157 throw badType(type); 00158 } 00159 00160 public Value convert(TypeChar type) throws ValueException { 00161 String s = this.toString(); 00162 final int max = type.getMax(); 00163 if (max > 0 && s.length() > max) s = s.substring(0, max); 00164 if (s.length() < max) { 00165 StringBuffer sb = new StringBuffer(s); 00166 while (sb.length() < max) sb.append(' '); 00167 s = sb.toString(); 00168 } 00169 return new ValueString(s); 00170 } 00171 00172 public Value convert(TypeClob type) throws ValueException { 00173 throw badType(type); 00174 } 00175 00176 public Value convert(TypeDate type) throws ValueException { 00177 throw badType(type); 00178 } 00179 00180 public Value convert(TypeDecimal type) throws ValueException { 00181 throw badType(type); 00182 } 00183 00184 public Value convert(TypeInt type) throws ValueException { 00185 throw badType(type); 00186 } 00187 00188 public Value convert(TypeInterval type) throws ValueException { 00189 throw badType(type); 00190 } 00191 00192 public Value convert(TypeReal type) throws ValueException { 00193 throw badType(type); 00194 } 00195 00196 public Value convert(TypeSmallInt type) throws ValueException { 00197 throw badType(type); 00198 } 00199 00200 public Value convert(TypeVarChar type) throws ValueException { 00201 String s = this.toString(); 00202 final int max = type.getMax(); 00203 if (max > 0 && s.length() > max) s = s.substring(0, max); 00204 return new ValueString(s); 00205 } 00206 00207 public Value convert(TypeVarBinary type) throws ValueException { 00208 throw badType(type); 00209 } 00210 00211 public Value convert(TypeTime type) throws ValueException { 00212 throw badType(type); 00213 } 00214 00215 public Value convert(TypeTimestamp type) throws ValueException { 00216 throw badType(type); 00217 } 00218 00219 public Value convert(TypeTinyInt type) throws ValueException { 00220 throw badType(type); 00221 } 00222 00223 00224 public Value binop(int op, ValueBlob v) throws ValueException { 00225 throw badBinop(op, v); 00226 } 00227 00228 public Value binop(int op, ValueBoolean v) throws ValueException { 00229 throw badBinop(op, v); 00230 } 00231 00232 public Value binop(int op, ValueByte v) throws ValueException { 00233 throw badBinop(op, v); 00234 } 00235 00236 public Value binop(int op, ValueClob v) throws ValueException { 00237 throw badBinop(op, v); 00238 } 00239 00240 public Value binop(int op, ValueDate v) throws ValueException { 00241 throw badBinop(op, v); 00242 } 00243 00244 public Value binop(int op, ValueDouble v) throws ValueException { 00245 throw badBinop(op, v); 00246 } 00247 00248 public Value binop(int op, ValueFloat v) throws ValueException { 00249 throw badBinop(op, v); 00250 } 00251 00252 public Value binop(int op, ValueInteger v) throws ValueException { 00253 throw badBinop(op, v); 00254 } 00255 00256 public Value binop(int op, ValueInterval v) throws ValueException { 00257 throw badBinop(op, v); 00258 } 00259 00260 public Value binop(int op, ValueLong v) throws ValueException { 00261 throw badBinop(op, v); 00262 } 00263 00264 public Value binop(int op, ValueNull v) throws ValueException { 00265 throw badBinop(op, v); 00266 } 00267 00268 public Value binop(int op, ValueOctets v) throws ValueException { 00269 throw badBinop(op, v); 00270 } 00271 00272 public Value binop(int op, ValuePattern v) throws ValueException { 00273 throw badBinop(op, v); 00274 } 00275 00276 public Value binop(int op, ValueScaledInteger v) throws ValueException { 00277 throw badBinop(op, v); 00278 } 00279 00280 public Value binop(int op, ValueShort v) throws ValueException { 00281 throw badBinop(op, v); 00282 } 00283 00284 public Value binop(int op, ValueString l) throws ValueException { 00285 return ValueString.binop_convert(op, l, this); 00286 } 00287 00288 public Value binop(int op, ValueTime v) throws ValueException { 00289 throw badBinop(op, v); 00290 } 00291 00292 public Value binop(int op, ValueTimestamp v) throws ValueException { 00293 throw badBinop(op, v); 00294 } 00295 00296 public Value binop(int op, ValueUnknown v) throws ValueException { 00297 return ValueUnknown.valueUnknown; 00298 } 00299 00300 public static final ValueException badBinop(int op, Value l, Value r) { 00301 return new ValueException("not implemented: " + 00302 l.getClass().getName() + " " + 00303 Op.toString(op) + " " + 00304 r.getClass().getName()); 00305 } 00306 00307 public final ValueException badBinop(int op, Value v) { 00308 return badBinop(op, this, v); 00309 } 00310 00311 public static final boolean isTrue(Value ret) throws ValueException { 00312 if (ret instanceof ValueBoolean) { 00313 return ((ValueBoolean)ret).isTrue(); 00314 } else if (ret instanceof ValueUnknown) { 00315 return false; 00316 } 00317 throw new ValueException("Not boolean: " + ret); 00318 } 00319 00320 public static final boolean boolOp(int op, Value l, Value r) 00321 throws ValueException 00322 { 00323 Value ret = binop(op, l, r); 00324 return isTrue(ret); 00325 } 00326 00327 public Value unop(int op) throws ValueException { 00328 throw new ValueException("not implemented: " + 00329 getClass().getName() + " unary op: " + 00330 Op.toString(op)); 00331 } 00332 00333 public static final boolean isNull(Value val) { 00334 return val instanceof ValueNull; 00335 } 00336 00337 public static final byte[] bytes(Value val) { 00338 try { 00339 ObjectOutputStream os = new ObjectOutputStream(null); 00340 os.writeObject(val); 00341 return os.toByteArray(); 00342 } catch (IOException e) { 00343 Debug.print(e); 00344 throw new RuntimeException(e.toString()); 00345 } 00346 } 00347 00348 public static final Value fromBytes(byte[] b) { 00349 try { 00350 ByteArrayInputStream bis = new ByteArrayInputStream(b); 00351 ObjectInputStream is = new ObjectInputStream(bis); 00352 return (Value)is.readObject(); 00353 } catch (Exception e) { 00354 Debug.print(e); 00355 throw new RuntimeException(e.toString()); 00356 } 00357 } 00358 00359 static final Hashtable javaTypes = new Hashtable(); 00360 static final void jc(String javaClass, String valueClass) { 00361 try { 00362 javaTypes.put(javaClass, Class.forName(valueClass)); 00363 } catch (ClassNotFoundException e) { 00364 Debug.print(e); 00365 } 00366 } 00367 00368 static { 00369 jc("[B", "com.quadcap.sql.types.ValueOctets"); 00370 jc("java.lang.Boolean", "com.quadcap.sql.types.ValueBoolean"); 00371 jc("java.lang.Byte", "com.quadcap.sql.types.ValueByte"); 00372 jc("java.lang.Double", "com.quadcap.sql.types.ValueDouble"); 00373 jc("java.lang.Float", "com.quadcap.sql.types.ValueFloat"); 00374 jc("java.lang.Integer", "com.quadcap.sql.types.ValueInteger"); 00375 jc("java.lang.Long", "com.quadcap.sql.types.ValueLong"); 00376 jc("java.lang.Short", "com.quadcap.sql.types.ValueShort"); 00377 jc("java.lang.String", "com.quadcap.sql.types.ValueString"); 00378 jc("java.math.BigDecimal", "com.quadcap.sql.types.ValueScaledInteger"); 00379 jc("java.sql.Date", "com.quadcap.sql.types.ValueDate"); 00380 jc("java.sql.Time", "com.quadcap.sql.types.ValueTime"); 00381 jc("java.sql.Timestamp", "com.quadcap.sql.types.ValueTimestamp"); 00382 jc("java.util.Date", "com.quadcap.sql.types.ValueTimestamp"); 00383 } 00384 00385 static final Hashtable jdbcTypes = new Hashtable(); 00386 static final void jdbcType(int typeNum, Type type) { 00387 jdbcTypes.put(new Integer(typeNum), type); 00388 } 00389 static { 00390 jdbcType(Types.BIT, TypeBoolean.typeBoolean); 00391 jdbcType(Types.TINYINT, TypeTinyInt.typeTinyInt); 00392 jdbcType(Types.SMALLINT, TypeSmallInt.typeSmallInt); 00393 jdbcType(Types.INTEGER, TypeInt.typeInt); 00394 jdbcType(Types.BIGINT, TypeBigInt.typeBigInt); 00395 jdbcType(Types.FLOAT, TypeReal.typeFloat); 00396 jdbcType(Types.REAL, TypeReal.typeReal); 00397 jdbcType(Types.DOUBLE, TypeReal.typeDouble); 00398 jdbcType(Types.NUMERIC, TypeDecimal.typeDecimal); 00399 jdbcType(Types.DECIMAL, TypeDecimal.typeDecimal); 00400 jdbcType(Types.CHAR, TypeChar.typeChar); 00401 jdbcType(Types.VARCHAR, TypeVarChar.typeVarChar); 00402 jdbcType(Types.LONGVARCHAR, TypeVarChar.typeVarChar); 00403 jdbcType(Types.DATE, TypeDate.typeDate); 00404 jdbcType(Types.TIME, TypeTime.typeTime); 00405 jdbcType(Types.TIMESTAMP, TypeTimestamp.typeTimestamp); 00406 jdbcType(Types.BINARY, TypeBinary.typeBinary); 00407 jdbcType(Types.VARBINARY, TypeVarBinary.typeVarBinary); 00408 jdbcType(Types.LONGVARBINARY, TypeVarBinary.typeVarBinary); 00409 // JAVA_OBJECT 00410 // DISTINCT 00411 // STRUCT 00412 // ARRAY 00413 //#ifndef JDK11 00414 jdbcType(Types.BLOB, TypeBlob.typeBlob); 00415 jdbcType(Types.CLOB, TypeClob.typeClob); 00416 //#endif 00417 // ref 00418 } 00419 00420 public static final Type typeForJdbcType(int type) { 00421 Type t = (Type)jdbcTypes.get(new Integer(type)); 00422 return t; 00423 } 00424 00425 public void setDatafile(Datafile db) {} 00426 00427 public static final Value fromObject(Object obj) throws ValueException { 00428 if (obj == null) return ValueNull.valueNull; 00429 Class valueClass = (Class)javaTypes.get(obj.getClass().getName()); 00430 if (valueClass != null) { 00431 try { 00432 Value v = (Value)(valueClass.newInstance()); 00433 v.fromJavaObject(obj); 00434 return v; 00435 } catch (IllegalAccessException e) { 00436 Debug.print(e); 00437 throw new ValueException(e.toString()); 00438 } catch (InstantiationException e) { 00439 Debug.print(e); 00440 throw new ValueException(e.toString()); 00441 } 00442 } 00443 throw new ValueException("No mapping for class: " + 00444 obj.getClass().getName()); 00445 } 00446 00447 }