1 33 package smallsql.database; 34 35 import java.math.BigDecimal ; 36 import java.sql.*; 37 38 39 public class ExpressionValue extends Expression { 40 41 private Object value; 42 private int dataType; 43 private int length; 44 45 48 ExpressionValue(){ 49 super(VALUE); 50 clear(); 51 } 52 53 56 ExpressionValue(int type){ 57 super(type); 58 switch(type){ 59 case GROUP_BY: 60 case SUM: 61 case FIRST: 62 case LAST: 63 clear(); 64 break; 65 case MIN: 66 case MAX: 67 break; 69 case COUNT: 70 value = new MutableInteger(0); 71 dataType = SQLTokenizer.INT; 72 break; 73 default: throw new Error (); 74 } 75 } 76 77 78 81 ExpressionValue(Object value, int dataType ){ 82 super(VALUE); 83 this.value = value; 84 this.dataType = dataType; 85 } 86 87 88 91 public boolean equals(Object expr){ 92 if(!super.equals(expr)) return false; 93 if(!(expr instanceof ExpressionValue)) return false; 94 Object v = ((ExpressionValue)expr).value; 95 if(v == value) return true; 96 if(value == null) return false; 97 return value.equals(v); 98 } 99 100 101 104 107 void accumulate(Expression expr) throws Exception { 108 int type = getType(); 109 if(type != GROUP_BY) expr = expr.getParams()[0]; 110 switch(type){ 111 case GROUP_BY: 112 case FIRST: 113 if(isEmpty()) set( expr.getObject(), expr.getDataType() ); 114 break; 115 case LAST: 116 set( expr.getObject(), expr.getDataType() ); 117 break; 118 case COUNT: 119 if(!expr.isNull()) ((MutableInteger)value).value++; 120 break; 121 case SUM: 122 if(isEmpty()){ 123 initValue( expr ); 124 }else 125 switch(dataType){ 126 case SQLTokenizer.TINYINT: 127 case SQLTokenizer.SMALLINT: 128 case SQLTokenizer.INT: 129 ((MutableInteger)value).value += expr.getInt(); 130 break; 131 case SQLTokenizer.BIGINT: 132 ((MutableLong)value).value += expr.getLong(); 133 break; 134 case SQLTokenizer.REAL: 135 ((MutableFloat)value).value += expr.getFloat(); 136 break; 137 case SQLTokenizer.FLOAT: 138 case SQLTokenizer.DOUBLE: 139 ((MutableDouble)value).value += expr.getDouble(); 140 break; 141 case SQLTokenizer.NUMERIC: 142 case SQLTokenizer.DECIMAL: 143 MutableNumeric newValue = expr.getNumeric(); 144 if(newValue != null) 145 ((MutableNumeric)value).add( newValue ); 146 break; 147 case SQLTokenizer.MONEY: 148 ((Money)value).value += expr.getMoney(); 149 break; 150 default: throw Utils.createSQLException("Unsupported data type "+SQLTokenizer.getKeyWord(dataType) +" for SUM function."); 151 } 152 break; 153 case MAX: 154 if(value == null){ 155 if(expr.isNull()) 156 dataType = expr.getDataType(); 157 else 158 initValue( expr ); 159 }else if(!expr.isNull()){ 160 switch(dataType){ 161 case SQLTokenizer.TINYINT: 162 case SQLTokenizer.SMALLINT: 163 case SQLTokenizer.INT: 164 ((MutableInteger)value).value = Math.max( ((MutableInteger)value).value, expr.getInt()); 165 break; 166 case SQLTokenizer.BIGINT: 167 ((MutableLong)value).value = Math.max( ((MutableLong)value).value, expr.getLong()); 168 break; 169 case SQLTokenizer.REAL: 170 ((MutableFloat)value).value = Math.max( ((MutableFloat)value).value, expr.getFloat()); 171 break; 172 case SQLTokenizer.FLOAT: 173 case SQLTokenizer.DOUBLE: 174 ((MutableDouble)value).value = Math.max( ((MutableDouble)value).value, expr.getDouble()); 175 break; 176 case SQLTokenizer.CHAR: 177 case SQLTokenizer.VARCHAR: 178 case SQLTokenizer.LONGVARCHAR: 179 String str = expr.getString(); 180 if(String.CASE_INSENSITIVE_ORDER.compare( value, str ) < 0) 181 value = str; 182 break; 183 case SQLTokenizer.NUMERIC: 184 case SQLTokenizer.DECIMAL: 185 MutableNumeric newValue = expr.getNumeric(); 186 if(((MutableNumeric)value).compareTo( newValue ) < 0) 187 value = newValue; 188 break; 189 case SQLTokenizer.MONEY: 190 ((Money)value).value = Math.max( ((Money)value).value, expr.getMoney()); 191 break; 192 case SQLTokenizer.TIMESTAMP: 193 case SQLTokenizer.SMALLDATETIME: 194 case SQLTokenizer.DATE: 195 case SQLTokenizer.TIME: 196 ((DateTime)value).time = Math.max( ((DateTime)value).time, expr.getLong()); 197 break; 198 default: throw new Error (""+dataType); 199 } 200 } 201 break; 202 case MIN: 203 if(value == null){ 204 if(expr.isNull()) 205 dataType = expr.getDataType(); 206 else 207 initValue( expr ); 208 }else if(!expr.isNull()){ 209 switch(dataType){ 210 case SQLTokenizer.TINYINT: 211 case SQLTokenizer.SMALLINT: 212 case SQLTokenizer.INT: 213 ((MutableInteger)value).value = Math.min( ((MutableInteger)value).value, expr.getInt()); 214 break; 215 case SQLTokenizer.BIGINT: 216 ((MutableLong)value).value = Math.min( ((MutableLong)value).value, expr.getLong()); 217 break; 218 case SQLTokenizer.REAL: 219 ((MutableFloat)value).value = Math.min( ((MutableFloat)value).value, expr.getFloat()); 220 break; 221 case SQLTokenizer.FLOAT: 222 case SQLTokenizer.DOUBLE: 223 ((MutableDouble)value).value = Math.min( ((MutableDouble)value).value, expr.getDouble()); 224 break; 225 case SQLTokenizer.CHAR: 226 case SQLTokenizer.VARCHAR: 227 case SQLTokenizer.LONGVARCHAR: 228 String str = expr.getString(); 229 if(String.CASE_INSENSITIVE_ORDER.compare( value, str ) > 0) 230 value = str; 231 break; 232 case SQLTokenizer.NUMERIC: 233 case SQLTokenizer.DECIMAL: 234 MutableNumeric newValue = expr.getNumeric(); 235 if(((MutableNumeric)value).compareTo( newValue ) > 0) 236 value = newValue; 237 break; 238 case SQLTokenizer.MONEY: 239 ((Money)value).value = Math.min( ((Money)value).value, expr.getMoney()); 240 break; 241 case SQLTokenizer.TIMESTAMP: 242 case SQLTokenizer.SMALLDATETIME: 243 case SQLTokenizer.DATE: 244 case SQLTokenizer.TIME: 245 ((DateTime)value).time = Math.min( ((DateTime)value).time, expr.getLong()); 246 break; 247 default: throw new Error (""+dataType); 248 } 249 } 250 break; 251 default: throw new Error (); 252 } 253 } 254 255 256 261 private void initValue(Expression expr) throws Exception { 262 dataType = expr.getDataType(); 263 switch(dataType){ 264 case SQLTokenizer.TINYINT: 265 case SQLTokenizer.SMALLINT: 266 case SQLTokenizer.INT: 267 value = new MutableInteger(expr.getInt()); 268 break; 269 case SQLTokenizer.BIGINT: 270 value = new MutableLong(expr.getLong()); 271 break; 272 case SQLTokenizer.REAL: 273 value = new MutableFloat(expr.getFloat()); 274 break; 275 case SQLTokenizer.FLOAT: 276 case SQLTokenizer.DOUBLE: 277 value = new MutableDouble(expr.getDouble()); 278 break; 279 case SQLTokenizer.SMALLMONEY: 280 case SQLTokenizer.MONEY: 281 value = Money.createFromUnscaledValue(expr.getMoney()); 282 break; 283 case SQLTokenizer.NUMERIC: 284 case SQLTokenizer.DECIMAL: 285 value = new MutableNumeric(expr.getNumeric()); 286 break; 287 case SQLTokenizer.TIMESTAMP: 288 case SQLTokenizer.SMALLDATETIME: 289 case SQLTokenizer.DATE: 290 case SQLTokenizer.TIME: 291 value = new DateTime(expr.getLong(), dataType); 292 break; 293 default: 294 value = expr.getObject(); 296 } 297 } 298 301 private static final Object EMPTY = new Object (); 302 final boolean isEmpty(){ 303 return value == EMPTY; 304 } 305 306 final void clear(){ 307 value = EMPTY; 308 } 309 310 311 final void set( Object value, int _dataType, int length ) throws SQLException{ 312 set( value, _dataType ); 313 this.length = length; 314 } 315 316 317 324 final void set( Object newValue, int newDataType ) throws SQLException{ 325 this.value = newValue; 326 this.dataType = newDataType; 327 if(dataType < 0){ 328 if(newValue == null) 329 this.dataType = SQLTokenizer.NULL; 330 else 331 if(newValue instanceof String ) 332 this.dataType = SQLTokenizer.VARCHAR; 333 else 334 if(newValue instanceof Byte ) 335 this.dataType = SQLTokenizer.TINYINT; 336 else 337 if(newValue instanceof Short ) 338 this.dataType = SQLTokenizer.SMALLINT; 339 else 340 if(newValue instanceof Integer ) 341 this.dataType = SQLTokenizer.INT; 342 else 343 if(newValue instanceof Long ) 344 this.dataType = SQLTokenizer.BIGINT; 345 else 346 if(newValue instanceof Float ) 347 this.dataType = SQLTokenizer.REAL; 348 else 349 if(newValue instanceof Double ) 350 this.dataType = SQLTokenizer.DOUBLE; 351 else 352 if(newValue instanceof Number ) 353 this.dataType = SQLTokenizer.DECIMAL; 354 else 355 if(newValue instanceof java.util.Date ){ 356 DateTime dateTime; 357 this.value = dateTime = DateTime.valueOf((java.util.Date )newValue); 358 this.dataType = dateTime.getDataType(); 359 }else 360 if(newValue instanceof byte[]) 361 this.dataType = SQLTokenizer.VARBINARY; 362 else 363 if(newValue instanceof Boolean ) 364 this.dataType = SQLTokenizer.BOOLEAN; 365 else 366 if(newValue instanceof Money) 367 this.dataType = SQLTokenizer.MONEY; 368 else 369 throw Utils.createSQLException("Unknown parameter class:" + newValue.getClass().getName()); 370 } 371 } 372 373 374 final void set(ExpressionValue val){ 375 this.value = val.value; 376 this.dataType = val.dataType; 377 this.length = val.length; 378 } 379 382 383 384 boolean isNull(){ 385 return value == null; 386 } 387 388 boolean getBoolean() throws Exception { 389 return getBoolean( value, dataType ); 390 } 391 392 static boolean getBoolean(Object obj, int dataType) throws Exception { 393 if(obj == null) return false; 394 switch(dataType){ 395 case SQLTokenizer.BIT: 396 case SQLTokenizer.BOOLEAN: 397 return (obj.equals(Boolean.TRUE)); 398 case SQLTokenizer.TINYINT: 399 case SQLTokenizer.SMALLINT: 400 case SQLTokenizer.INT: 401 case SQLTokenizer.BIGINT: 402 return ((Number )obj).intValue() != 0; 403 case SQLTokenizer.REAL: 404 case SQLTokenizer.DOUBLE: 405 case SQLTokenizer.MONEY: 406 return ((Number )obj).doubleValue() != 0; 407 default: return Utils.string2boolean( obj.toString() ); 408 } 409 } 410 411 int getInt() throws Exception { 412 return getInt( value, dataType ); 413 } 414 415 static int getInt(Object obj, int dataType) throws Exception { 416 if(obj == null) return 0; 417 switch(dataType){ 418 case SQLTokenizer.BIT: 419 case SQLTokenizer.BOOLEAN: 420 return (obj == Boolean.TRUE) ? 1 : 0; 421 case SQLTokenizer.TINYINT: 422 case SQLTokenizer.SMALLINT: 423 case SQLTokenizer.INT: 424 case SQLTokenizer.BIGINT: 425 case SQLTokenizer.REAL: 426 case SQLTokenizer.FLOAT: 427 case SQLTokenizer.DOUBLE: 428 case SQLTokenizer.MONEY: 429 return ((Number )obj).intValue(); 430 case SQLTokenizer.TIMESTAMP: 431 case SQLTokenizer.TIME: 432 case SQLTokenizer.DATE: 433 case SQLTokenizer.SMALLDATETIME: 434 return (int)((DateTime)obj).getTimeMillis(); 435 default: 436 String str = obj.toString().trim(); 437 try{ 438 return Integer.parseInt( str ); 439 }catch(Throwable th){} 440 return (int)Double.parseDouble( str ); 441 } 442 } 443 444 long getLong() throws Exception { 445 return getLong(value, dataType); 446 } 447 448 static long getLong(Object obj, int dataType) throws Exception { 449 if(obj == null) return 0; 450 switch(dataType){ 451 case SQLTokenizer.BIT: 452 case SQLTokenizer.BOOLEAN: 453 return (obj == Boolean.TRUE) ? 1 : 0; 454 case SQLTokenizer.TINYINT: 455 case SQLTokenizer.SMALLINT: 456 case SQLTokenizer.INT: 457 case SQLTokenizer.BIGINT: 458 case SQLTokenizer.DOUBLE: 459 case SQLTokenizer.MONEY: 460 return ((Number )obj).longValue(); 461 case SQLTokenizer.TIMESTAMP: 462 case SQLTokenizer.TIME: 463 case SQLTokenizer.DATE: 464 case SQLTokenizer.SMALLDATETIME: 465 return ((DateTime)obj).getTimeMillis(); 466 default: 467 String str = obj.toString(); 468 if(str.indexOf('-') > 0 || str.indexOf(':') > 0) 469 return DateTime.parse(str); 470 try{ 471 return Long.parseLong( str ); 472 }catch(NumberFormatException e){ 473 return (long)Double.parseDouble( str ); 474 } 475 } 476 } 477 478 float getFloat() throws Exception { 479 return getFloat( value, dataType); 480 } 481 482 static float getFloat(Object obj, int dataType) throws Exception { 483 if(obj == null) return 0; 484 switch(dataType){ 485 case SQLTokenizer.BIT: 486 return (obj.equals(Boolean.TRUE)) ? 1 : 0; 487 case SQLTokenizer.INT: 488 case SQLTokenizer.BIGINT: 489 case SQLTokenizer.DOUBLE: 490 case SQLTokenizer.FLOAT: 491 case SQLTokenizer.REAL: 492 case SQLTokenizer.MONEY: 493 return ((Number )obj).floatValue(); 494 case SQLTokenizer.TIMESTAMP: 495 case SQLTokenizer.TIME: 496 case SQLTokenizer.DATE: 497 case SQLTokenizer.SMALLDATETIME: 498 return ((DateTime)obj).getTimeMillis(); 499 default: return Float.parseFloat( obj.toString() ); 500 } 501 } 502 503 double getDouble() throws Exception { 504 return getDouble( value, dataType); 505 } 506 507 static double getDouble(Object obj, int dataType) throws Exception { 508 if(obj == null) return 0; 509 switch(dataType){ 510 case SQLTokenizer.BIT: 511 return (obj.equals(Boolean.TRUE)) ? 1 : 0; 512 case SQLTokenizer.INT: 513 case SQLTokenizer.BIGINT: 514 case SQLTokenizer.DOUBLE: 515 case SQLTokenizer.MONEY: 516 return ((Number )obj).doubleValue(); 517 case SQLTokenizer.TIMESTAMP: 518 case SQLTokenizer.TIME: 519 case SQLTokenizer.DATE: 520 case SQLTokenizer.SMALLDATETIME: 521 return ((DateTime)obj).getTimeMillis(); 522 default: return Double.parseDouble( obj.toString() ); 523 } 524 } 525 526 527 long getMoney() throws Exception { 528 return getMoney( value, dataType ); 529 } 530 531 532 static long getMoney(Object obj, int dataType) throws Exception { 533 if(obj == null) return 0; 534 switch(dataType){ 535 case SQLTokenizer.BIT: 536 return (obj == Boolean.TRUE) ? 10000 : 0; 537 case SQLTokenizer.TINYINT: 538 case SQLTokenizer.SMALLINT: 539 case SQLTokenizer.INT: 540 case SQLTokenizer.BIGINT: 541 return ((Number )obj).longValue() * 10000; 542 case SQLTokenizer.REAL: 543 case SQLTokenizer.FLOAT: 544 case SQLTokenizer.DOUBLE: 545 return Utils.doubleToMoney(((Number )obj).doubleValue()); 546 case SQLTokenizer.MONEY: 547 case SQLTokenizer.SMALLMONEY: 548 return ((Money)obj).value; 549 default: return Money.parseMoney( obj.toString() ); 550 } 551 } 552 553 554 MutableNumeric getNumeric(){ 555 return getNumeric(value, dataType ); 556 } 557 558 559 static MutableNumeric getNumeric(Object obj, int dataType){ 560 if(obj == null) return null; 561 switch(dataType){ 562 case SQLTokenizer.BIT: 563 return new MutableNumeric( (obj == Boolean.TRUE) ? 1 : 0); 564 case SQLTokenizer.INT: 565 return new MutableNumeric( ((Number )obj).intValue() ); 566 case SQLTokenizer.BIGINT: 567 return new MutableNumeric( ((Number )obj).longValue() ); 568 case SQLTokenizer.REAL: 569 float fValue = ((Number )obj).floatValue(); 570 if(Float.isInfinite(fValue) || Float.isNaN(fValue)) 571 return null; 572 return new MutableNumeric( fValue ); 573 case SQLTokenizer.FLOAT: 574 case SQLTokenizer.DOUBLE: 575 double dValue = ((Number )obj).doubleValue(); 576 if(Double.isInfinite(dValue) || Double.isNaN(dValue)) 577 return null; 578 return new MutableNumeric( dValue ); 579 case SQLTokenizer.MONEY: 580 case SQLTokenizer.SMALLMONEY: 581 return new MutableNumeric( ((Money)obj).value, 4 ); 582 case SQLTokenizer.DECIMAL: 583 case SQLTokenizer.NUMERIC: 584 if(obj instanceof MutableNumeric) 585 return (MutableNumeric)obj; 586 return new MutableNumeric( (BigDecimal )obj ); 587 default: return new MutableNumeric( obj.toString() ); 588 } 589 } 590 591 592 Object getObject(){ 593 return value; 594 } 595 596 String getString(){ 597 if(value == null) return null; 598 if(dataType == SQLTokenizer.BIT){ 599 return (value == Boolean.TRUE) ? "1" : "0"; 600 } 601 return value.toString(); 602 } 603 604 byte[] getBytes() throws Exception { 605 return getBytes( value, dataType); 606 } 607 608 609 static byte[] getBytes(Object obj, int dataType) throws Exception { 610 if(obj == null) return null; 611 switch(dataType){ 612 case SQLTokenizer.BINARY: 613 case SQLTokenizer.VARBINARY: 614 return (byte[])obj; 615 case SQLTokenizer.VARCHAR: 616 case SQLTokenizer.CHAR: 617 case SQLTokenizer.NVARCHAR: 618 case SQLTokenizer.NCHAR: 619 return ((String )obj).getBytes(); 620 case SQLTokenizer.INT: 621 return Utils.int2bytes( ((Number )obj).intValue() ); 622 case SQLTokenizer.UNIQUEIDENTIFIER: 623 return Utils.unique2bytes((String )obj); 624 default: throw createUnspportedConversion(dataType, obj, SQLTokenizer.VARBINARY); 625 } 626 } 627 628 629 630 final int getDataType(){ 631 return dataType; 632 } 633 634 639 640 String getTableName(){ 641 return null; 642 } 643 644 final int getPrecision(){ 645 switch(dataType){ 646 case SQLTokenizer.VARCHAR: 647 case SQLTokenizer.CHAR: 648 return ((String )value).length(); 649 case SQLTokenizer.VARBINARY: 650 case SQLTokenizer.BINARY: 651 return ((byte[])value).length; 652 default: 653 return super.getPrecision(); 654 } 655 } 656 657 658 int getScale(){ 659 switch(dataType){ 660 case SQLTokenizer.DECIMAL: 661 case SQLTokenizer.NUMERIC: 662 MutableNumeric obj = getNumeric(); 663 return (obj == null) ? 0: obj.getScale(); 664 default: 665 return getScale(dataType); 666 } 667 } 668 669 670 static SQLException createUnspportedConversion( int fromDataType, Object obj, int toDataType ){ 671 return Utils.createSQLException("Can't convert '" + 672 SQLTokenizer.getKeyWord(fromDataType) + 673 "' [" + obj + ']' + 674 "' to '" + 675 SQLTokenizer.getKeyWord(toDataType) + '\''); 676 } 677 678 679 } | Popular Tags |