|                                                                                                              1
 21
 22  package org.apache.derby.iapi.types;
 23
 24  import org.apache.derby.iapi.reference.SQLState;
 25
 26  import org.apache.derby.iapi.services.io.ArrayInputStream;
 27
 28  import org.apache.derby.iapi.error.StandardException;
 29  import org.apache.derby.iapi.db.DatabaseContext;
 30
 31  import org.apache.derby.iapi.types.DataValueDescriptor;
 32  import org.apache.derby.iapi.types.TypeId;
 33
 34  import org.apache.derby.iapi.types.NumberDataValue;
 35  import org.apache.derby.iapi.types.DateTimeDataValue;
 36
 37  import org.apache.derby.iapi.services.io.StoredFormatIds;
 38  import org.apache.derby.iapi.services.context.ContextService;
 39
 40  import org.apache.derby.iapi.services.sanity.SanityManager;
 41  import org.apache.derby.iapi.types.DataType;
 42  import org.apache.derby.iapi.services.i18n.LocaleFinder;
 43  import org.apache.derby.iapi.services.cache.ClassSize;
 44  import org.apache.derby.iapi.util.StringUtil;
 45  import org.apache.derby.iapi.util.ReuseFactory;
 46
 47  import org.apache.derby.iapi.types.SQLDouble;
 48  import org.apache.derby.iapi.types.SQLTime;
 49
 50  import java.sql.Date
  ; 51  import java.sql.Time
  ; 52  import java.sql.Timestamp
  ; 53  import java.sql.Types
  ; 54  import java.sql.ResultSet
  ; 55  import java.sql.SQLException
  ; 56  import java.sql.PreparedStatement
  ; 57
 58  import java.util.Calendar
  ; 59  import java.util.GregorianCalendar
  ; 60
 61  import java.io.ObjectOutput
  ; 62  import java.io.ObjectInput
  ; 63  import java.io.IOException
  ; 64
 65  import java.text.DateFormat
  ; 66  import java.text.ParseException
  ; 67
 68
 83
 84  public final class SQLTimestamp extends DataType
 85                          implements DateTimeDataValue
 86  {
 87
 88      static final int MAX_FRACTION_DIGITS = 6;     static final int FRACTION_TO_NANO = 1000;
 91      static final int ONE_BILLION = 1000000000;
 92
 93      private int encodedDate;
 94      private int encodedTime;
 95      private int nanos;
 96
 97          private String
  valueString; 99
 100
 104
 105     private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( SQLTimestamp.class);
 106
 107     public int estimateMemoryUsage()
 108     {
 109         int sz = BASE_MEMORY_USAGE + ClassSize.estimateMemoryUsage( valueString);
 110         return sz;
 111     }
 113     public String
  getString() 114     {
 115         if (!isNull())
 116         {
 117             if (valueString == null)
 118             {
 119                 valueString = getTimestamp((Calendar
  ) null).toString(); 120
 124                 int separatorIdx = valueString.indexOf( '-');
 125                 if( separatorIdx >= 0 && separatorIdx < 4)
 126                 {
 127                     StringBuffer
  sb = new StringBuffer  (); 128                     for( ; separatorIdx < 4; separatorIdx++)
 129                         sb.append('0');
 130                     sb.append( valueString);
 131                     valueString = sb.toString();
 132                 }
 133             }
 134
 135             return valueString;
 136         }
 137         else
 138         {
 139             if (SanityManager.DEBUG)
 140             {
 141                 if (valueString != null)
 142                 {
 143                     SanityManager.THROWASSERT(
 144                         "valueString expected to be null, not " +
 145                         valueString);
 146                 }
 147             }
 148             return null;
 149         }
 150     }
 151
 152
 153
 161     public Date
  getDate( Calendar  cal) throws StandardException 162     {
 163         if (isNull())
 164             return null;
 165         return newDate(cal);
 166     }
 167
 168     private Date
  newDate(java.util.Calendar  cal) throws StandardException 169     {
 170         if( cal == null)
 171             cal = new GregorianCalendar
  (); 172         cal.clear();
 173         cal.set(Calendar.YEAR, SQLDate.getYear(encodedDate) );
 174         cal.set(Calendar.MONTH, SQLDate.getMonth(encodedDate)-1);
 175         cal.set(Calendar.DATE, SQLDate.getDay(encodedDate) );
 176         cal.set(Calendar.HOUR_OF_DAY, 0);
 177         cal.set(Calendar.MINUTE, 0);
 178         cal.set(Calendar.SECOND, 0);
 179         cal.set(Calendar.MILLISECOND, 0);
 180         return new Date
  (cal.getTime().getTime()); 181     }
 182
 183
 190     public Time getTime( Calendar
  cal) throws StandardException 191     {
 192         if (isNull())
 193             return null;
 194         return newTime(cal);
 195     }
 196
 197     private Time newTime(java.util.Calendar
  cal) throws StandardException 198     {
 199         if( cal == null)
 200             cal = new GregorianCalendar
  (); 201         cal.clear();
 202         cal.set(Calendar.YEAR, 1970);
 203         cal.set(Calendar.MONTH, Calendar.JANUARY);
 204         cal.set(Calendar.DATE, 1);
 205         cal.set(Calendar.HOUR_OF_DAY, SQLTime.getHour(encodedTime));
 206         cal.set(Calendar.MINUTE, SQLTime.getMinute(encodedTime));
 207         cal.set(Calendar.SECOND, SQLTime.getSecond(encodedTime));
 208         cal.set(Calendar.MILLISECOND, (int)(nanos/1000000));
 209         return new Time(cal.getTime().getTime());
 210     }
 211
 212     public Object
  getObject() 213     {
 214         return getTimestamp((Calendar
  ) null); 215     }
 216
 217
 218     public int getLength()
 219     {
 220         return 12;
 221     }
 222
 223
 224     public String
  getTypeName() 225     {
 226         return "TIMESTAMP";
 227     }
 228
 229
 232
 233
 238     public int getTypeFormatId() {
 239         return StoredFormatIds.SQL_TIMESTAMP_ID;
 240     }
 241
 242
 246     public void writeExternal(ObjectOutput
  out) throws IOException  { 247
 248         if (SanityManager.DEBUG)
 249             SanityManager.ASSERT(!isNull(), "writeExternal() is not supposed to be called for null values.");
 250
 251
 255         out.writeInt(encodedDate);
 256         out.writeInt(encodedTime);
 257         out.writeInt(nanos);
 258     }
 259
 260
 265     public void readExternal(ObjectInput
  in) throws IOException  266     {
 267         encodedDate = in.readInt();
 268         encodedTime = in.readInt();
 269         nanos = in.readInt();
 270                 valueString = null;
 272     }
 273     public void readExternalFromArray(ArrayInputStream in) throws IOException
  274     {
 275         encodedDate = in.readInt();
 276         encodedTime = in.readInt();
 277         nanos = in.readInt();
 278                 valueString = null;
 280     }
 281
 282
 285
 286
 287     public DataValueDescriptor getClone()
 288     {
 289                 return new SQLTimestamp(encodedDate, encodedTime, nanos);
 291     }
 292
 293
 296     public DataValueDescriptor getNewNull()
 297     {
 298         return new SQLTimestamp();
 299     }
 300
 304     public void restoreToNull()
 305     {
 306                 encodedDate = 0;
 308         encodedTime = 0;
 309         nanos = 0;
 310
 311                 valueString = null;
 313     }
 314
 315
 318
 319
 324     public void setValueFromResultSet(ResultSet
  resultSet, int colNumber, 325                                       boolean isNullable)
 326         throws SQLException
  , StandardException 327     {
 328             setValue(resultSet.getTimestamp(colNumber), (Calendar
  ) null); 329     }
 330
 331     public int compare(DataValueDescriptor other)
 332         throws StandardException
 333     {
 334
 337         if (typePrecedence() < other.typePrecedence())
 338         {
 339             return - (other.compare(this));
 340         }
 341
 342         boolean thisNull, otherNull;
 343
 344         thisNull = this.isNull();
 345         otherNull = other.isNull();
 346
 347
 353         if (thisNull || otherNull)
 354         {
 355             if (!thisNull)                      return -1;
 357             if (!otherNull)                     return 1;
 359             return 0;
 360         }
 361
 362
 365
 366         int comparison;
 367
 368         int otherEncodedDate = 0;
 369         int otherEncodedTime = 0;
 370         int otherNanos = 0;
 371
 372
 374         if (other instanceof SQLTimestamp)
 375         {
 376             SQLTimestamp st = (SQLTimestamp)other;
 377             otherEncodedDate= st.encodedDate;
 378             otherEncodedTime= st.encodedTime;
 379             otherNanos= st.nanos;
 380         }
 381         else
 382         {
 383
 386             Calendar
  cal = new GregorianCalendar  (); 387             Timestamp
  otherts = other.getTimestamp(cal); 388             otherEncodedDate = SQLTimestamp.computeEncodedDate(otherts, cal);
 389             otherEncodedTime = SQLTimestamp.computeEncodedTime(otherts, cal);
 390             otherNanos = otherts.getNanos();
 391         }
 392         if (encodedDate < otherEncodedDate)
 393             comparison = -1;
 394         else if (encodedDate > otherEncodedDate)
 395             comparison = 1;
 396         else if (encodedTime < otherEncodedTime)
 397             comparison = -1;
 398         else if (encodedTime > otherEncodedTime)
 399             comparison = 1;
 400         else if (nanos < otherNanos)
 401             comparison = -1;
 402         else if (nanos > otherNanos)
 403             comparison = 1;
 404         else
 405             comparison = 0;
 406
 407         return comparison;
 408     }
 409
 410
 413     public boolean compare(int op,
 414                            DataValueDescriptor other,
 415                            boolean orderedNulls,
 416                            boolean unknownRV)
 417         throws StandardException
 418     {
 419         if (!orderedNulls)              {
 421             if (this.isNull() || ((DataValueDescriptor)other).isNull())
 422                 return unknownRV;
 423         }
 424
 425
 426         return super.compare(op, other, orderedNulls, unknownRV);
 427     }
 428
 429
 432
 433
 436
 437
 438     public SQLTimestamp() { }
 439
 440
 441     public SQLTimestamp(Timestamp
  value) throws StandardException 442     {
 443         setValue(value, (Calendar
  ) null); 444     }
 445
 446     SQLTimestamp(int encodedDate, int encodedTime, int nanos) {
 447
 448         this.encodedDate = encodedDate;
 449         this.encodedTime = encodedTime;
 450         this.nanos = nanos;
 451     }
 452
 453     public SQLTimestamp( DataValueDescriptor date, DataValueDescriptor time) throws StandardException
 454     {
 455         Calendar
  cal = null; 456         if( date == null || date.isNull()
 457             || time == null || time.isNull())
 458             return;
 459         if( date instanceof SQLDate)
 460         {
 461             SQLDate sqlDate = (SQLDate) date;
 462             encodedDate = sqlDate.getEncodedDate();
 463         }
 464         else
 465         {
 466             cal = new GregorianCalendar
  (); 467             encodedDate = computeEncodedDate( date.getDate( cal), cal);
 468         }
 469         if( time instanceof SQLTime)
 470         {
 471             SQLTime sqlTime = (SQLTime) time;
 472             encodedTime = sqlTime.getEncodedTime();
 473         }
 474         else
 475         {
 476             if( cal == null)
 477                 cal = new GregorianCalendar
  (); 478             encodedTime = computeEncodedTime( time.getTime( cal), cal);
 479         }
 480     }
 481
 482
 491     public SQLTimestamp( String
  timestampStr, boolean isJDBCEscape, LocaleFinder localeFinder) 492         throws StandardException
 493     {
 494         parseTimestamp( timestampStr, isJDBCEscape,localeFinder, (Calendar
  ) null); 495     }
 496
 497
 506     public SQLTimestamp( String
  timestampStr, boolean isJDBCEscape, LocaleFinder localeFinder, Calendar  cal) 507         throws StandardException
 508     {
 509         parseTimestamp( timestampStr, isJDBCEscape, localeFinder, cal);
 510     }
 511
 512     static final char DATE_SEPARATOR = '-';
 513     private static final char[] DATE_SEPARATORS = { DATE_SEPARATOR};
 514     private static final char IBM_DATE_TIME_SEPARATOR = '-';
 515     private static final char ODBC_DATE_TIME_SEPARATOR = ' ';
 516     private static final char[] DATE_TIME_SEPARATORS = {IBM_DATE_TIME_SEPARATOR, ODBC_DATE_TIME_SEPARATOR};
 517     private static final char[] DATE_TIME_SEPARATORS_OR_END
 518     = {IBM_DATE_TIME_SEPARATOR, ODBC_DATE_TIME_SEPARATOR, (char) 0};
 519     private static final char IBM_TIME_SEPARATOR = '.';
 520     private static final char ODBC_TIME_SEPARATOR = ':';
 521     private static final char[] TIME_SEPARATORS = {IBM_TIME_SEPARATOR, ODBC_TIME_SEPARATOR};
 522     private static final char[] TIME_SEPARATORS_OR_END = {IBM_TIME_SEPARATOR, ODBC_TIME_SEPARATOR, (char) 0};
 523     private static final char[] END_OF_STRING = {(char) 0};
 524
 525     private void parseTimestamp( String
  timestampStr, boolean isJDBCEscape, LocaleFinder localeFinder, Calendar  cal) 526         throws StandardException
 527     {
 528         StandardException thrownSE = null;
 529         DateTimeParser parser = new DateTimeParser( timestampStr);
 530         try
 531         {
 532             int[] dateTimeNano = parseDateOrTimestamp( parser, true);
 533             encodedDate = dateTimeNano[0];
 534             encodedTime = dateTimeNano[1];
 535             nanos = dateTimeNano[2];
 536             valueString = parser.getTrimmedString();
 537             return;
 538         }
 539         catch( StandardException se)
 540         {
 541             thrownSE = se;
 542         }
 543                 try
 545         {
 546             timestampStr = StringUtil.trimTrailing( timestampStr);
 547             int[] dateAndTime = parseLocalTimestamp( timestampStr, localeFinder, cal);
 548             encodedDate = dateAndTime[0];
 549             encodedTime = dateAndTime[1];
 550             valueString = timestampStr;
 551             return;
 552         }
 553         catch( ParseException
  pe){} 554         catch( StandardException se){}
 555         if( thrownSE != null)
 556             throw thrownSE;
 557         throw StandardException.newException( SQLState.LANG_DATE_SYNTAX_EXCEPTION);
 558     }
 560
 570     static int[] parseLocalTimestamp( String
  str, LocaleFinder localeFinder, Calendar  cal) 571         throws StandardException, ParseException
  572     {
 573         DateFormat
  timestampFormat = null; 574         if(localeFinder == null)
 575             timestampFormat = DateFormat.getDateTimeInstance();
 576         else if( cal == null)
 577             timestampFormat = localeFinder.getTimestampFormat();
 578         else
 579             timestampFormat = (DateFormat
  ) localeFinder.getTimestampFormat().clone(); 580         if( cal == null)
 581             cal = new GregorianCalendar
  (); 582         else
 583             timestampFormat.setCalendar( cal);
 584         java.util.Date
  date = timestampFormat.parse( str); 585
 586         return new int[] { computeEncodedDate( date, cal), computeEncodedTime( date, cal)};
 587     }
 589
 603     static int[] parseDateOrTimestamp( DateTimeParser parser, boolean timeRequired)
 604         throws StandardException
 605     {
 606         int year = parser.parseInt( 4, false, DATE_SEPARATORS, false);
 607         int month = parser.parseInt( 2, true, DATE_SEPARATORS, false);
 608         int day = parser.parseInt( 2, true, timeRequired ? DATE_TIME_SEPARATORS : DATE_TIME_SEPARATORS_OR_END, false);
 609         int hour = 0;
 610         int minute = 0;
 611         int second = 0;
 612         int nano = 0;
 613         if( parser.getCurrentSeparator() != 0)
 614         {
 615             char timeSeparator = (parser.getCurrentSeparator() == ODBC_DATE_TIME_SEPARATOR)
 616               ? ODBC_TIME_SEPARATOR : IBM_TIME_SEPARATOR;
 617             hour = parser.parseInt( 2, true, TIME_SEPARATORS, false);
 618             if( timeSeparator == parser.getCurrentSeparator())
 619             {
 620                 minute = parser.parseInt( 2, false, TIME_SEPARATORS, false);
 621                 if( timeSeparator == parser.getCurrentSeparator())
 622                 {
 623                     second = parser.parseInt( 2, false, TIME_SEPARATORS_OR_END, false);
 624                     if( parser.getCurrentSeparator() == '.')
 625                         nano = parser.parseInt( MAX_FRACTION_DIGITS, true, END_OF_STRING, true)*FRACTION_TO_NANO;
 626                 }
 627             }
 628         }
 629         parser.checkEnd();
 630         return new int[] { SQLDate.computeEncodedDate( year, month, day),
 631                            SQLTime.computeEncodedTime( hour,minute,second),
 632                            nano};
 633     }
 635
 639     void setObject(Object
  theValue) throws StandardException 640     {
 641         setValue((Timestamp
  ) theValue); 642     }
 643
 644     protected void setFrom(DataValueDescriptor theValue) throws StandardException {
 645
 646         if (theValue instanceof SQLTimestamp) {
 647             restoreToNull();
 648             SQLTimestamp tvst = (SQLTimestamp) theValue;
 649             encodedDate = tvst.encodedDate;
 650             encodedTime = tvst.encodedTime;
 651             nanos = tvst.nanos;
 652         }
 653         else
 654         {
 655             Calendar
  cal = new GregorianCalendar  (); 656             setValue(theValue.getTimestamp( cal), cal);
 657         }
 658     }
 659
 660
 665     public void setValue(Date
  value, Calendar  cal) throws StandardException 666     {
 667         restoreToNull();
 668         if( value != null)
 669         {
 670             if( cal == null)
 671                 cal = new GregorianCalendar
  (); 672             encodedDate = computeEncodedDate(value, cal);
 673         }
 674
 675     }
 676
 677
 681     public void setValue(Time value, Calendar
  cal) throws StandardException 682     {
 683         restoreToNull();
 684         if (value != null)
 685         {
 686
 692             Calendar
  today = GregorianCalendar.getInstance(); 693             encodedDate = SQLDate.computeEncodedDate(today);
 694             if( cal == null)
 695                 cal = today;
 696             encodedTime = computeEncodedTime(value, cal);
 697         }
 698     }
 699
 700
 704     public void setValue(Timestamp
  value, Calendar  cal) 705         throws StandardException
 706     {
 707         restoreToNull();
 708         setNumericTimestamp(value, cal);
 709     }
 710
 711
 712     public void setValue(String
  theValue) 713         throws StandardException
 714     {
 715         restoreToNull();
 716
 717         if (theValue != null)
 718         {
 719             DatabaseContext databaseContext = (DatabaseContext) ContextService.getContext(DatabaseContext.CONTEXT_ID);
 720             parseTimestamp( theValue,
 721                             false,
 722                             (databaseContext == null) ? null : databaseContext.getDatabase(),
 723                             (Calendar
  ) null); 724         }
 725
 726     }
 727
 728
 731
 732
 733
 738     public NumberDataValue getYear(NumberDataValue result)
 739                             throws StandardException
 740     {
 741         if (SanityManager.DEBUG)
 742         {
 743             SanityManager.ASSERT(!isNull(), "getYear called on a null");
 744         }
 745         return SQLDate.setSource(SQLDate.getYear(encodedDate), result);
 746     }
 747
 748
 753     public NumberDataValue getMonth(NumberDataValue result)
 754                             throws StandardException
 755     {
 756         if (SanityManager.DEBUG)
 757         {
 758             SanityManager.ASSERT(!isNull(), "getMonth called on a null");
 759         }
 760         return SQLDate.setSource(SQLDate.getMonth(encodedDate), result);
 761     }
 762
 763
 768     public NumberDataValue getDate(NumberDataValue result)
 769                             throws StandardException
 770     {
 771         if (SanityManager.DEBUG)
 772         {
 773             SanityManager.ASSERT(!isNull(), "getDate called on a null");
 774         }
 775         return SQLDate.setSource(SQLDate.getDay(encodedDate), result);
 776     }
 777
 778
 783     public NumberDataValue getHours(NumberDataValue result)
 784                             throws StandardException
 785     {
 786         if (SanityManager.DEBUG)
 787         {
 788             SanityManager.ASSERT(!isNull(), "getHours called on a null");
 789         }
 790         return SQLDate.setSource(SQLTime.getHour(encodedTime), result);
 791     }
 792
 793
 798     public NumberDataValue getMinutes(NumberDataValue result)
 799                             throws StandardException
 800     {
 801         if (SanityManager.DEBUG)
 802         {
 803             SanityManager.ASSERT(!isNull(), "getMinute called on a null");
 804         }
 805         return SQLDate.setSource(SQLTime.getMinute(encodedTime), result);
 806     }
 807
 808
 813     public NumberDataValue getSeconds(NumberDataValue source)
 814                             throws StandardException
 815     {
 816         if (SanityManager.DEBUG)
 817         {
 818             SanityManager.ASSERT(!isNull(), "getSeconds called on a null");
 819             SanityManager.ASSERT(source == null || source instanceof SQLDouble,
 820         "getSeconds for a timestamp was given a source other than a SQLDouble");
 821         }
 822         NumberDataValue result;
 823
 824         if (source != null)
 825             result = source;
 826         else
 827             result = new SQLDouble();
 828
 829         result.setValue((double)(SQLTime.getSecond(encodedTime))
 830                 + ((double)nanos)/1.0e9);
 831
 832         return result;
 833     }
 834
 835
 838
 839     public String
  toString() 840     {
 841         if (isNull())
 842         {
 843             return "NULL";
 844         }
 845         else
 846         {
 847             return getTimestamp( (Calendar
  ) null).toString(); 848         }
 849     }
 850
 851
 854     public int hashCode()
 855     {
 856         if (isNull())
 857         {
 858             return 0;
 859         }
 860
 861         return  encodedDate + encodedTime + nanos;
 863     }
 864
 865
 866     public int  typePrecedence()
 867     {
 868         return TypeId.TIMESTAMP_PRECEDENCE;
 869     }
 870
 871
 876     public final boolean isNull()
 877     {
 878         return (encodedDate == 0);
 879     }
 880
 881
 887     public Timestamp
  getTimestamp(java.util.Calendar  cal) 888     {
 889         if (isNull())
 890             return null;
 891         return newTimestamp(cal);
 892     }
 893
 894     private Timestamp
  newTimestamp(Calendar  currentCal) 895     {
 896         if( currentCal == null)
 897             currentCal = new GregorianCalendar
  (); 898         setCalendar( currentCal);
 899         Timestamp
  t = new Timestamp  (currentCal.getTime().getTime()); 900         t.setNanos(nanos);
 901         return t;
 902     }
 903
 904     private void setCalendar( Calendar
  cal) 905     {
 906         cal.clear();
 907         cal.set(Calendar.YEAR, SQLDate.getYear(encodedDate));
 908
 909         cal.set(Calendar.MONTH, (SQLDate.getMonth(encodedDate)-1));
 910         cal.set(Calendar.DATE, SQLDate.getDay(encodedDate));
 911         cal.set(Calendar.HOUR_OF_DAY, SQLTime.getHour(encodedTime));
 912         cal.set(Calendar.MINUTE, SQLTime.getMinute(encodedTime));
 913         cal.set(Calendar.SECOND, SQLTime.getSecond(encodedTime));
 914         cal.set(Calendar.MILLISECOND, 0);
 915     }
 917
 921     private void setNumericTimestamp(Timestamp
  value, Calendar  cal) throws StandardException 922     {
 923         if (SanityManager.DEBUG)
 924         {
 925             SanityManager.ASSERT(isNull(), "setNumericTimestamp called when already set");
 926         }
 927         if (value != null)
 928         {
 929             if( cal == null)
 930                 cal = new GregorianCalendar
  (); 931             encodedDate = computeEncodedDate(value, cal);
 932             encodedTime = computeEncodedTime(value, cal);
 933             nanos = value.getNanos();
 934         }
 935
 936     }
 937
 938
 940
 946     protected String
  getNationalString(LocaleFinder localeFinder) throws StandardException 947     {
 948         if (isNull())
 949         {
 950             return getString();
 951         }
 952
 953
 954         return localeFinder.getTimestampFormat().format(getTimestamp((Calendar
  ) null)); 955     }
 956
 957
 966     private static int computeEncodedDate(java.util.Date
  value, Calendar  currentCal) throws StandardException 967     {
 968         if (value == null)
 969             return 0;
 970
 971         currentCal.setTime(value);
 972         return SQLDate.computeEncodedDate(currentCal);
 973     }
 974
 983     private static int computeEncodedTime(java.util.Date
  value, Calendar  currentCal) throws StandardException 984     {
 985         currentCal.setTime(value);
 986         return SQLTime.computeEncodedTime(currentCal);
 987     }
 988
 989
 990     public void setInto(PreparedStatement
  ps, int position) throws SQLException  , StandardException { 991
 992                   ps.setTimestamp(position, getTimestamp((Calendar
  ) null)); 993      }
 994
 995
 1000    public static DateTimeDataValue computeTimestampFunction( DataValueDescriptor operand,
 1001                                                              DataValueFactory dvf) throws StandardException
 1002    {
 1003        try
 1004        {
 1005            if( operand.isNull())
 1006                return new SQLTimestamp();
 1007            if( operand instanceof SQLTimestamp)
 1008                return (SQLTimestamp) operand.getClone();
 1009
 1010            String
  str = operand.getString(); 1011            if( str.length() == 14)
 1012            {
 1013                int year = parseDateTimeInteger( str, 0, 4);
 1014                int month = parseDateTimeInteger( str, 4, 2);
 1015                int day = parseDateTimeInteger( str, 6, 2);
 1016                int hour = parseDateTimeInteger( str, 8, 2);
 1017                int minute = parseDateTimeInteger( str, 10, 2);
 1018                int second = parseDateTimeInteger( str, 12, 2);
 1019                return new SQLTimestamp( SQLDate.computeEncodedDate( year, month, day),
 1020                                         SQLTime.computeEncodedTime( hour,minute,second),
 1021                                         0);
 1022            }
 1023                        return dvf.getTimestampValue( str, false);
 1025        }
 1026        catch( StandardException se)
 1027        {
 1028            if( SQLState.LANG_DATE_SYNTAX_EXCEPTION.startsWith( se.getSQLState()))
 1029                throw StandardException.newException( SQLState.LANG_INVALID_FUNCTION_ARGUMENT,
 1030                                                      operand.getString(), "timestamp");
 1031            throw se;
 1032        }
 1033    }
 1035    static int parseDateTimeInteger( String
  str, int start, int ndigits) throws StandardException 1036    {
 1037        int end = start + ndigits;
 1038        int retVal = 0;
 1039        for( int i = start; i < end; i++)
 1040        {
 1041            char c = str.charAt( i);
 1042            if( !Character.isDigit( c))
 1043                throw StandardException.newException( SQLState.LANG_DATE_SYNTAX_EXCEPTION);
 1044            retVal = 10*retVal + Character.digit( c, 10);
 1045        }
 1046        return retVal;
 1047    }
 1049
 1063    public DateTimeDataValue timestampAdd( int intervalType,
 1064                                           NumberDataValue count,
 1065                                           java.sql.Date
  currentDate, 1066                                           DateTimeDataValue resultHolder)
 1067        throws StandardException
 1068    {
 1069        if( resultHolder == null)
 1070            resultHolder = new SQLTimestamp();
 1071        SQLTimestamp tsResult = (SQLTimestamp) resultHolder;
 1072        if( isNull() || count.isNull())
 1073        {
 1074            tsResult.restoreToNull();
 1075            return resultHolder;
 1076        }
 1077        tsResult.setFrom( this);
 1078        int intervalCount = count.getInt();
 1079
 1080        switch( intervalType)
 1081        {
 1082        case FRAC_SECOND_INTERVAL:
 1083                        long nanos = this.nanos + intervalCount;
 1085            if( nanos >= 0 && nanos < ONE_BILLION)
 1086                tsResult.nanos = (int) nanos;
 1087            else
 1088            {
 1089                int secondsInc = (int)(nanos/ONE_BILLION);
 1090                if( nanos >= 0)
 1091                    tsResult.nanos = (int) (nanos % ONE_BILLION);
 1092                else
 1093                {
 1094                    secondsInc--;
 1095                    nanos -= secondsInc * (long)ONE_BILLION;                     tsResult.nanos = (int) nanos;
 1097                }
 1098                addInternal( Calendar.SECOND, secondsInc, tsResult);
 1099            }
 1100            break;
 1101
 1102        case SECOND_INTERVAL:
 1103            addInternal( Calendar.SECOND, intervalCount, tsResult);
 1104            break;
 1105
 1106        case MINUTE_INTERVAL:
 1107            addInternal( Calendar.MINUTE, intervalCount, tsResult);
 1108            break;
 1109
 1110        case HOUR_INTERVAL:
 1111            addInternal( Calendar.HOUR, intervalCount, tsResult);
 1112            break;
 1113
 1114        case DAY_INTERVAL:
 1115            addInternal( Calendar.DATE, intervalCount, tsResult);
 1116            break;
 1117
 1118        case WEEK_INTERVAL:
 1119            addInternal( Calendar.DATE, intervalCount*7, tsResult);
 1120            break;
 1121
 1122        case MONTH_INTERVAL:
 1123            addInternal( Calendar.MONTH, intervalCount, tsResult);
 1124            break;
 1125
 1126        case QUARTER_INTERVAL:
 1127            addInternal( Calendar.MONTH, intervalCount*3, tsResult);
 1128            break;
 1129
 1130        case YEAR_INTERVAL:
 1131            addInternal( Calendar.YEAR, intervalCount, tsResult);
 1132            break;
 1133
 1134        default:
 1135            throw StandardException.newException( SQLState.LANG_INVALID_FUNCTION_ARGUMENT,
 1136                                                  ReuseFactory.getInteger( intervalType),
 1137                                                  "TIMESTAMPADD");
 1138        }
 1139        return tsResult;
 1140    }
 1142    private void addInternal( int calIntervalType, int count, SQLTimestamp tsResult) throws StandardException
 1143    {
 1144        Calendar
  cal = new GregorianCalendar  (); 1145        setCalendar( cal);
 1146        try
 1147        {
 1148            cal.add( calIntervalType, count);
 1149            tsResult.encodedTime = SQLTime.computeEncodedTime( cal);
 1150            tsResult.encodedDate = SQLDate.computeEncodedDate( cal);
 1151        }
 1152        catch( StandardException se)
 1153        {
 1154            String
  state = se.getSQLState(); 1155            if( state != null && state.length() > 0 && SQLState.LANG_DATE_RANGE_EXCEPTION.startsWith( state))
 1156            {
 1157                throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "TIMESTAMP");
 1158            }
 1159            throw se;
 1160        }
 1161    }
 1163
 1178    public NumberDataValue timestampDiff( int intervalType,
 1179                                          DateTimeDataValue time1,
 1180                                          java.sql.Date
  currentDate, 1181                                          NumberDataValue resultHolder)
 1182        throws StandardException
 1183    {
 1184        if( resultHolder == null)
 1185            resultHolder = new SQLInteger();
 1186
 1187       if( isNull() || time1.isNull())
 1188        {
 1189            resultHolder.setToNull();
 1190            return resultHolder;
 1191        }
 1192
 1193        SQLTimestamp ts1 = promote( time1, currentDate);
 1194
 1195
 1198        Calendar
  cal = new GregorianCalendar  (); 1199        setCalendar( cal);
 1200        long thisInSeconds = cal.getTime().getTime()/1000;
 1201        ts1.setCalendar( cal);
 1202        long ts1InSeconds = cal.getTime().getTime()/1000;
 1203        long secondsDiff = thisInSeconds - ts1InSeconds;
 1204        int nanosDiff = nanos - ts1.nanos;
 1205                if( nanosDiff < 0 && secondsDiff > 0)
 1207        {
 1208            secondsDiff--;
 1209            nanosDiff += ONE_BILLION;
 1210        }
 1211        else if( nanosDiff > 0 && secondsDiff < 0)
 1212        {
 1213            secondsDiff++;
 1214            nanosDiff -= ONE_BILLION;
 1215        }
 1216        long ldiff = 0;
 1217
 1218        switch( intervalType)
 1219        {
 1220        case FRAC_SECOND_INTERVAL:
 1221            if( secondsDiff > Integer.MAX_VALUE/ONE_BILLION || secondsDiff < Integer.MIN_VALUE/ONE_BILLION)
 1222                throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1223            ldiff = secondsDiff*ONE_BILLION + nanosDiff;
 1224            break;
 1225
 1226        case SECOND_INTERVAL:
 1227            ldiff = secondsDiff;
 1228            break;
 1229
 1230        case MINUTE_INTERVAL:
 1231            ldiff = secondsDiff/60;
 1232            break;
 1233
 1234        case HOUR_INTERVAL:
 1235            ldiff = secondsDiff/(60*60);
 1236            break;
 1237
 1238        case DAY_INTERVAL:
 1239            ldiff = secondsDiff/(24*60*60);
 1240            break;
 1241
 1242        case WEEK_INTERVAL:
 1243            ldiff = secondsDiff/(7*24*60*60);
 1244            break;
 1245
 1246        case QUARTER_INTERVAL:
 1247        case MONTH_INTERVAL:
 1248                        if( Math.abs( secondsDiff) > 366*24*60*60)                 ldiff = 12*(secondsDiff/(366*24*60*60));
 1251            else
 1252                ldiff = secondsDiff/(31*24*60*60);
 1253            if( secondsDiff >= 0)
 1254            {
 1255                if (ldiff >= Integer.MAX_VALUE)
 1256                    throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1257                                cal.add( Calendar.MONTH, (int) (ldiff + 1));
 1259                for(;;)
 1260                {
 1261                    if( cal.getTime().getTime()/1000 > thisInSeconds)
 1262                        break;
 1263                    cal.add( Calendar.MONTH, 1);
 1264                    ldiff++;
 1265                }
 1266            }
 1267            else
 1268            {
 1269                if (ldiff <= Integer.MIN_VALUE)
 1270                    throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1271                                cal.add( Calendar.MONTH, (int) (ldiff - 1));
 1273                for(;;)
 1274                {
 1275                    if( cal.getTime().getTime()/1000 < thisInSeconds)
 1276                        break;
 1277                    cal.add( Calendar.MONTH, -1);
 1278                    ldiff--;
 1279                }
 1280            }
 1281            if( intervalType == QUARTER_INTERVAL)
 1282                ldiff = ldiff/3;
 1283            break;
 1284
 1285        case YEAR_INTERVAL:
 1286                        ldiff = secondsDiff/(366*24*60*60);
 1288            if( secondsDiff >= 0)
 1289            {
 1290                if (ldiff >= Integer.MAX_VALUE)
 1291                    throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1292                                cal.add( Calendar.YEAR, (int) (ldiff + 1));
 1294                for(;;)
 1295                {
 1296                    if( cal.getTime().getTime()/1000 > thisInSeconds)
 1297                        break;
 1298                    cal.add( Calendar.YEAR, 1);
 1299                    ldiff++;
 1300                }
 1301            }
 1302            else
 1303            {
 1304                if (ldiff <= Integer.MIN_VALUE)
 1305                    throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1306                                cal.add( Calendar.YEAR, (int) (ldiff - 1));
 1308                for(;;)
 1309                {
 1310                    if( cal.getTime().getTime()/1000 < thisInSeconds)
 1311                        break;
 1312                    cal.add( Calendar.YEAR, -1);
 1313                    ldiff--;
 1314                }
 1315            }
 1316            break;
 1317
 1318        default:
 1319            throw StandardException.newException( SQLState.LANG_INVALID_FUNCTION_ARGUMENT,
 1320                                                  ReuseFactory.getInteger( intervalType),
 1321                                                  "TIMESTAMPDIFF");
 1322        }
 1323        if (ldiff > Integer.MAX_VALUE || ldiff < Integer.MIN_VALUE)
 1324            throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, "INTEGER");
 1325        resultHolder.setValue( (int) ldiff);
 1326        return resultHolder;
 1327    }
 1329
 1338    static SQLTimestamp promote( DateTimeDataValue dateTime, java.sql.Date
  currentDate) throws StandardException 1339    {
 1340        if( dateTime instanceof SQLTimestamp)
 1341            return (SQLTimestamp) dateTime;
 1342        else if( dateTime instanceof SQLTime)
 1343            return new SQLTimestamp( SQLDate.computeEncodedDate( currentDate, (Calendar
  ) null), 1344                                    ((SQLTime) dateTime).getEncodedTime(),
 1345                                    0 );
 1346        else if( dateTime instanceof SQLDate)
 1347            return new SQLTimestamp( ((SQLDate) dateTime).getEncodedDate(), 0, 0);
 1348        else
 1349            return new SQLTimestamp( dateTime.getTimestamp( new GregorianCalendar
  ())); 1350    } }
 1352
                                                                                                                                                                                                             |                                                                       
 
 
 
 
 
                                                                                   Popular Tags                                                                                                                                                                                              |