1 24 25 package com.mckoi.database; 26 27 import com.mckoi.database.global.SQLTypes; 28 import com.mckoi.database.global.ByteLongObject; 29 import com.mckoi.database.global.CastHelper; 30 import com.mckoi.util.BigNumber; 31 import com.mckoi.util.StringUtil; 32 import java.util.Date ; 33 import java.util.List ; 34 35 42 43 public abstract class TType implements java.io.Serializable { 44 45 static final long serialVersionUID = 5866230818579853961L; 46 47 50 private int sql_type; 51 52 55 protected TType(int sql_type) { 56 this.sql_type = sql_type; 57 } 58 59 62 public int getSQLType() { 63 return sql_type; 64 } 65 66 72 public String asSQLString() { 73 return DataTableColumnDef.sqlTypeToString(getSQLType()); 74 } 75 76 77 83 public abstract boolean comparableTypes(TType type); 84 85 91 public abstract int compareObs(Object ob1, Object ob2); 92 93 97 public abstract int calculateApproximateMemoryUse(Object ob); 98 99 103 public abstract Class javaClass(); 104 105 106 107 109 113 private static String parseQuotedString(String str) { 114 if (str.startsWith("'") && str.endsWith("'")) { 115 return str.substring(1, str.length() - 1); 116 } 117 else { 118 throw new RuntimeException ("String is not quoted: " + str); 119 } 120 } 121 122 126 public static String asEncodedString(TType type) { 127 StringBuffer buf = new StringBuffer (); 128 if (type instanceof TBooleanType) { 129 buf.append("BOOLEAN("); 130 buf.append(type.getSQLType()); 131 buf.append(')'); 132 } 133 else if (type instanceof TStringType) { 134 TStringType str_type = (TStringType) type; 135 buf.append("STRING("); 136 buf.append(type.getSQLType()); 137 buf.append(','); 138 buf.append(str_type.getMaximumSize()); 139 buf.append(",'"); 140 buf.append(str_type.getLocaleString()); 141 buf.append("',"); 142 buf.append(str_type.getStrength()); 143 buf.append(','); 144 buf.append(str_type.getDecomposition()); 145 buf.append(')'); 146 } 147 else if (type instanceof TNumericType) { 148 TNumericType num_type = (TNumericType) type; 149 buf.append("NUMERIC("); 150 buf.append(type.getSQLType()); 151 buf.append(','); 152 buf.append(num_type.getSize()); 153 buf.append(','); 154 buf.append(num_type.getScale()); 155 buf.append(')'); 156 } 157 else if (type instanceof TBinaryType) { 158 TBinaryType bin_type = (TBinaryType) type; 159 buf.append("BINARY("); 160 buf.append(type.getSQLType()); 161 buf.append(','); 162 buf.append(bin_type.getMaximumSize()); 163 buf.append(')'); 164 } 165 else if (type instanceof TDateType) { 166 buf.append("DATE("); 167 buf.append(type.getSQLType()); 168 buf.append(')'); 169 } 170 else if (type instanceof TNullType) { 171 buf.append("NULL("); 172 buf.append(type.getSQLType()); 173 buf.append(')'); 174 } 175 else if (type instanceof TJavaObjectType) { 176 buf.append("JAVAOBJECT("); 177 buf.append(type.getSQLType()); 178 buf.append(",'"); 179 buf.append(((TJavaObjectType) type).getJavaClassTypeString()); 180 buf.append("')"); 181 } 182 else { 183 throw new RuntimeException ("Can not encode type: " + type); 184 } 185 return new String (buf); 186 } 187 188 193 public static String asEncodedString(TType[] types) { 194 StringBuffer buf = new StringBuffer (); 195 for (int i = 0; i < types.length; ++i) { 196 buf.append(asEncodedString(types[i])); 197 if (i < types.length - 1) { 198 buf.append("!|"); 199 } 200 } 201 return new String (buf); 202 } 203 204 208 public static TType decodeString(String encoded_str) { 209 int param_s = encoded_str.indexOf('('); 210 int param_e = encoded_str.lastIndexOf(')'); 211 String params = encoded_str.substring(param_s + 1, param_e); 212 List param_list = StringUtil.explode(params, ","); 213 int sql_type = Integer.parseInt((String ) param_list.get(0)); 214 215 if (encoded_str.startsWith("BOOLEAN(")) { 216 return new TBooleanType(sql_type); 217 } 218 else if (encoded_str.startsWith("STRING(")) { 219 int size = Integer.parseInt((String ) param_list.get(1)); 220 String locale_str = parseQuotedString((String ) param_list.get(2)); 221 if (locale_str.length() == 0) { 222 locale_str = null; 223 } 224 int strength = Integer.parseInt((String ) param_list.get(3)); 225 int decomposition = Integer.parseInt((String ) param_list.get(4)); 226 return new TStringType(sql_type, size, 227 locale_str, strength, decomposition); 228 } 229 else if (encoded_str.startsWith("NUMERIC(")) { 230 int size = Integer.parseInt((String ) param_list.get(1)); 231 int scale = Integer.parseInt((String ) param_list.get(2)); 232 return new TNumericType(sql_type, size, scale); 233 } 234 else if (encoded_str.startsWith("BINARY(")) { 235 int size = Integer.parseInt((String ) param_list.get(1)); 236 return new TBinaryType(sql_type, size); 237 } 238 else if (encoded_str.startsWith("DATE(")) { 239 return new TDateType(sql_type); 240 } 241 else if (encoded_str.startsWith("NULL(")) { 242 return new TNullType(); 243 } 244 else if (encoded_str.startsWith("JAVAOBJECT(")) { 245 String class_str = parseQuotedString((String ) param_list.get(1)); 246 return new TJavaObjectType(class_str); 247 } 248 else { 249 throw new RuntimeException ("Can not parse encoded string: " + encoded_str); 250 } 251 } 252 253 257 public static TType[] decodeTypes(String encoded_str) { 258 List items = StringUtil.explode(encoded_str, "!|"); 259 260 if (items.size() == 1) { 262 if (items.get(0).equals("")) { 263 return new TType[0]; 264 } 265 } 266 267 int sz = items.size(); 268 TType[] return_types = new TType[sz]; 269 for (int i = 0; i < sz; ++i) { 270 String str = (String ) items.get(i); 271 return_types[i] = decodeString(str); 272 } 273 return return_types; 274 } 275 276 277 279 282 public static TType javaObjectType(String class_name) { 283 return new TJavaObjectType(class_name); 284 } 285 286 290 public static TType stringType(int sql_type, int size, 291 String locale, int strength, int decomposition) { 292 293 return new TStringType(sql_type, size, locale, strength, decomposition); 294 } 295 296 299 public static TType numericType(int sql_type, int size, int scale) { 300 return new TNumericType(sql_type, size, scale); 301 } 302 303 306 public static TType booleanType(int sql_type) { 307 return new TBooleanType(sql_type); 308 } 309 310 313 public static TType dateType(int sql_type) { 314 return new TDateType(sql_type); 315 } 316 317 320 public static TType binaryType(int sql_type, int size) { 321 return new TBinaryType(sql_type, size); 322 } 323 324 326 331 public static Object castObjectToTType(Object ob, TType type) { 332 if (ob == null) { 334 return null; 335 } 336 337 int size = -1; 338 int scale = -1; 339 int sql_type = type.getSQLType(); 340 341 if (type instanceof TStringType) { 342 size = ((TStringType) type).getMaximumSize(); 343 } 344 else if (type instanceof TNumericType) { 345 TNumericType num_type = (TNumericType) type; 346 size = num_type.getSize(); 347 scale = num_type.getScale(); 348 } 349 else if (type instanceof TBinaryType) { 350 size = ((TBinaryType) type).getMaximumSize(); 351 } 352 353 ob = CastHelper.castObjectToSQLType(ob, type.getSQLType(), size, scale, 354 DataTableColumnDef.sqlTypeToString(sql_type)); 355 356 return ob; 357 } 358 359 369 public static TType fromClass(Class c) { 370 if (c == String .class) { 371 return STRING_TYPE; 372 } 373 else if (c == BigNumber.class) { 374 return NUMERIC_TYPE; 375 } 376 else if (c == java.util.Date .class) { 377 return DATE_TYPE; 378 } 379 else if (c == Boolean .class) { 380 return BOOLEAN_TYPE; 381 } 382 else if (c == ByteLongObject.class) { 383 return BINARY_TYPE; 384 } 385 else { 386 throw new Error ("Don't know how to convert " + c + " to a TType."); 387 } 388 389 } 390 391 392 399 public static TType getWidestType(TType t1, TType t2) { 400 int t1SQLType = t1.getSQLType(); 401 int t2SQLType = t2.getSQLType(); 402 if (t1SQLType == SQLTypes.DECIMAL) { 403 return t1; 404 } 405 if (t2SQLType == SQLTypes.DECIMAL) { 406 return t2; 407 } 408 if (t1SQLType == SQLTypes.NUMERIC) { 409 return t1; 410 } 411 if (t2SQLType == SQLTypes.NUMERIC) { 412 return t2; 413 } 414 415 if (t1SQLType == SQLTypes.BIT) { 416 return t2; } 418 if (t2SQLType == SQLTypes.BIT) { 419 return t1; 420 } 421 422 int t1IntSize = getIntSize(t1SQLType); 423 int t2IntSize = getIntSize(t2SQLType); 424 if (t1IntSize > 0 && t2IntSize > 0) { 425 return (t1IntSize > t2IntSize)?t1:t2; 427 } 428 429 int t1FloatSize = getFloatSize(t1SQLType); 430 int t2FloatSize = getFloatSize(t2SQLType); 431 if (t1FloatSize > 0 && t2FloatSize > 0) { 432 return (t1FloatSize > t2FloatSize)?t1:t2; 434 } 435 436 if (t1FloatSize > t2IntSize) { 437 return t1; 438 } 439 if (t2FloatSize > t1IntSize) { 440 return t2; 441 } 442 if (t1IntSize >= t2FloatSize || t2IntSize >= t1FloatSize) { 443 return new TNumericType(SQLTypes.DOUBLE,8,-1); 445 } 446 throw new Error ("Widest type error."); 449 } 450 451 460 private static int getIntSize(int sqlType) { 461 switch (sqlType) { 462 case SQLTypes.TINYINT: 463 return 1; 464 case SQLTypes.SMALLINT: 465 return 2; 466 case SQLTypes.INTEGER: 467 return 4; 468 case SQLTypes.BIGINT: 469 return 8; 470 default: 471 return 0; 472 } 473 } 474 475 484 private static int getFloatSize(int sqlType) { 485 switch (sqlType) { 486 default: 487 return 0; 488 case SQLTypes.REAL: 489 return 4; 490 case SQLTypes.FLOAT: 491 case SQLTypes.DOUBLE: 492 return 8; 493 } 494 } 495 496 497 498 500 503 public static final TBooleanType BOOLEAN_TYPE = new TBooleanType(SQLTypes.BIT); 504 505 509 public static final TStringType STRING_TYPE = new TStringType( 510 SQLTypes.VARCHAR, -1, (String ) null); 511 512 515 public static final TNumericType NUMERIC_TYPE = 516 new TNumericType(SQLTypes.NUMERIC, -1, -1); 517 518 521 public static final TDateType DATE_TYPE = new TDateType(SQLTypes.TIMESTAMP); 522 523 526 public static final TBinaryType BINARY_TYPE = 527 new TBinaryType(SQLTypes.BLOB, -1); 528 529 532 public static final TNullType NULL_TYPE = new TNullType(); 533 534 537 public static final TQueryPlanType QUERY_PLAN_TYPE = new TQueryPlanType(); 538 539 542 public static final TArrayType ARRAY_TYPE = new TArrayType(); 543 544 } 545 | Popular Tags |