KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > smallsql > database > StoreImpl


1 /* =============================================================
2  * SmallSQL : a free Java DBMS library for the Java(tm) platform
3  * =============================================================
4  *
5  * (C) Copyright 2004-2006, by Volker Berlin.
6  *
7  * Project Info: http://www.smallsql.de/
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * ---------------
28  * StoreImpl.java
29  * ---------------
30  * Author: Volker Berlin
31  *
32  */

33 package smallsql.database;
34
35 import java.io.*;
36 import java.sql.SQLException JavaDoc;
37
38
39 public class StoreImpl extends Store {
40
41     private static final int DEFAULT_PAGE_SIZE = 8192; // 8 Kb
42
private static final int PAGE_MAGIC = 0x12DD13DE; // are used for repairing a table
43
/**
44      * The structur of the Page Control Block is:
45      * 4 byte - page magic
46      * 4 Byte - Status 0:normal; 1:deleted; 2:Pointer to an update; 3: updated page
47      * 4 Byte - used size of the page
48      * 4 byte - physical size of the page
49      * 4 byte - offset to the next page
50      * 8 byte - position of an updated page
51      */

52     private static final int PAGE_CONTROL_SIZE = 28;
53     private static final byte[] page_control = new byte[PAGE_CONTROL_SIZE];
54     private int status; // valid value are follow:
55
private static final int NORMAL = 0;
56     private static final int DELETED = 1;
57     /**
58      * Using of UPDATE_POINTER and UPDATED_PAGE
59      * If a page are updated and the new data are larger as the old data then
60      * the old page are changed to a UPDATE_POINTER. The new page is
61      * a UPDATED_PAGE. On reading the pages only the UPDATE_POINTER is read.
62      * The UPDATED_PAGE are skipped. Thats a row change not it position.
63      */

64     private static final int UPDATE_POINTER = 2;
65     private static final int UPDATED_PAGE = 3;
66     
67     final private Table table;
68     private byte[] page; // Daten einer Page
69
private StorePage storePage;
70     private long filePos; // Position in der Datei
71
private int sizeUsed;
72     private int sizePhysical;
73     private int nextPageOffset;
74     private long filePosUpdated;
75     private int type;
76     
77     private StoreImpl updatePointer;
78
79     private StoreImpl( Table table, StorePage storePage, int type, long filePos ){
80         this.table = table;
81         this.storePage = storePage;
82         this.filePos = filePos;
83         this.type = type;
84     }
85     
86     
87     /** folgende Arten von StoreImpl Types sind möglich
88         INSERT: Eine Page die neue Daten enthalten wird. filePos ist noch nicht spezifiziert.
89         CREATE: Eine spezielle Art von INSERT.
90         SELECT: Nur Leseoperationen sind möglich.
91         UPDATE: Hat eine filePos, wenn neue größe zu klein, muß alte Page gelöscht werden, und neue hinzugefügt werden.
92         DELETE: hat keinen Cache sondern nur die filePos, um das flag zu schreiben.
93     */

94     static StoreImpl createStore( Table table, StorePage storePage, int type, long filePos ) throws Exception JavaDoc{
95         StoreImpl store = new StoreImpl(table, storePage, type, filePos);
96         RandomAccessFile raFile = storePage.raFile;
97         switch(type){
98             case SQLTokenizer.LONGVARBINARY:
99                 // wird verwendet zum speichern von LONGVARBINARY und LONGVARCHAR
100
store.page = new byte[(int)filePos + PAGE_CONTROL_SIZE];
101                 store.filePos = -1;
102                 break;
103             case SQLTokenizer.INSERT:
104             case SQLTokenizer.CREATE:
105                 store.page = new byte[DEFAULT_PAGE_SIZE];
106                 break;
107             case SQLTokenizer.SELECT:
108             case SQLTokenizer.UPDATE:
109             case SQLTokenizer.DELETE:
110                 if(storePage.page == null){
111                     if(filePos >= raFile.length()-PAGE_CONTROL_SIZE) return null;
112                     raFile.seek(filePos);
113                     synchronized(page_control){
114                         raFile.read(page_control);
115                         store.page = page_control;
116                         store.readPageHeader();
117                     }
118                     store.page = new byte[store.sizeUsed];
119                     raFile.seek(filePos);
120                     raFile.read(store.page);
121                 }else{
122                     store.page = storePage.page;
123                     store.readPageHeader();
124                 }
125                 store = store.loadUpdatedStore();
126                 break;
127             default: throw new Error JavaDoc();
128         }
129         store.offset = PAGE_CONTROL_SIZE;
130         return store;
131     }
132     
133     
134     /**
135      * Recreate a StoreImpl from an uncommited StorePage.
136      */

137     static StoreImpl recreateStore( Table table, StorePage storePage, int type) throws Exception JavaDoc{
138         StoreImpl store = new StoreImpl(table, storePage, type, -1);
139         store.page = storePage.page;
140         store.readPageHeader();
141         store = store.loadUpdatedStore();
142         store.offset = PAGE_CONTROL_SIZE;
143         return store;
144     }
145     
146     
147     private final void readPageHeader() throws SQLException JavaDoc{
148         if(readInt() != PAGE_MAGIC)
149             throw Utils.createSQLException("Corrupt table page at position:"+filePos);
150         status = readInt();
151         sizeUsed = readInt();
152         sizePhysical = readInt();
153         nextPageOffset = readInt();
154         filePosUpdated = readLong();
155     }
156     
157     
158     final private StoreImpl loadUpdatedStore() throws Exception JavaDoc{
159         if(status != UPDATE_POINTER) return this;
160         StoreImpl storeTemp = table.getStore( ((TableStorePage)storePage).con, filePosUpdated, type);
161         storeTemp.updatePointer = this;
162         return storeTemp;
163     }
164     
165
166     private void resizePage(int minNewSize){
167         int newSize = Math.max(minNewSize, page.length*2);
168         byte[] newPage = new byte[newSize];
169         System.arraycopy( page, 0, newPage, 0, page.length);
170         page = newPage;
171     }
172     
173
174     boolean isValidPage(){
175         return status == NORMAL || (status == UPDATED_PAGE && updatePointer != null);
176     }
177     
178     int getUsedSize(){
179         return sizeUsed;
180     }
181     
182     long getNextPagePos(){
183         if(updatePointer != null) return updatePointer.getNextPagePos();
184         if(nextPageOffset <= 0){
185             nextPageOffset = sizePhysical;
186         }
187         return filePos + nextPageOffset;
188     }
189
190     
191     /**
192      *
193      * @param con Is needed to add this page to the commitPages. If it null then it save directly without rollback option.
194      * @return The file position if con == null.
195      * @throws SQLException
196      */

197     long writeFinsh(SSConnection con) throws SQLException JavaDoc{
198         switch(type){
199             case SQLTokenizer.LONGVARBINARY:
200             case SQLTokenizer.INSERT:
201             case SQLTokenizer.CREATE:
202                 sizeUsed = sizePhysical = offset;
203                 break;
204             case SQLTokenizer.UPDATE:
205                 if(status != UPDATE_POINTER) {
206                     sizeUsed = offset;
207                     break;
208                 }
209             case SQLTokenizer.DELETE:
210                 sizeUsed = PAGE_CONTROL_SIZE;
211                 break;
212             //SQLTokenizer.SELECT should not occur here
213
default: throw new Error JavaDoc(""+type);
214         }
215         offset = 0;
216         writeInt( PAGE_MAGIC ); // for repair
217
writeInt( status);
218         writeInt( sizeUsed );
219         writeInt( sizePhysical );
220         writeInt( 0 ); //nextPageOffset
221
writeLong( filePosUpdated ); // Pointer of an updated page
222
storePage.setPageData( page, sizeUsed ); //TODO page sollte eigentlich beim einlesen gesetzt sein
223
if(con == null){
224             // the pointer is needed to safe in another page
225
// this produce not referenced pages on rollback
226
return storePage.commit();
227         }else{
228             return 0;
229         }
230     }
231     
232     
233     final private void createWriteLock() throws SQLException JavaDoc{
234         TableStorePage storePageWrite = table.requestWriteLock( ((TableStorePage)storePage).con, (TableStorePage)storePage );
235         if(storePageWrite == null)
236             throw Utils.createSQLException("Row is locked from another Connection");
237         storePage = storePageWrite;
238     }
239     
240     /**
241      * Is call from updateRow().
242      * The offset of newData must be at the end of the data. It is used as new page size.
243      */

244     void updateFinsh(SSConnection con, StoreImpl newData) throws SQLException JavaDoc{
245         type = SQLTokenizer.UPDATE;
246         createWriteLock();
247         if(newData.offset <= sizePhysical || filePos == -1){
248             // the old page can be overwrite because it it large enough
249
page = newData.page; //newData is only a temp StoreImpl
250
offset = newData.offset;
251             if(sizePhysical < offset) sizePhysical = offset; // occur only on updates of not commited inserts (filePos == -1
252
writeFinsh(con);
253         }else{
254             // we need to create a new page because the old page is to small
255
newData.status = UPDATED_PAGE;
256             if(updatePointer == null){
257                 // we need to create a new page and change the old page to a UPDATE_POINTER
258
((TableStorePage)newData.storePage).lockType = TableView.LOCK_INSERT;
259                 filePosUpdated = newData.writeFinsh(null);
260                 status = UPDATE_POINTER;
261             }else{
262                 // we need to create a new page and delete the old page
263
((TableStorePage)newData.storePage).lockType = TableView.LOCK_INSERT;
264                 updatePointer.filePosUpdated = newData.writeFinsh(null);
265                 updatePointer.status = UPDATE_POINTER;
266                 updatePointer.type = SQLTokenizer.UPDATE;
267                 updatePointer.createWriteLock();
268                 updatePointer.writeFinsh(con);
269                 status = DELETED;
270             }
271             writeFinsh(con);
272         }
273     }
274     
275 /*==============================================================================
276
277 Write und Read Methoden
278
279 ==============================================================================*/

280     private int offset; // aktuelle read/write Position in der Page
281

282     
283     int getCurrentOffsetInPage(){
284         return offset;
285     }
286     
287     
288     void setCurrentOffsetInPage(int newOffset){
289         this.offset = newOffset;
290     }
291     
292
293     void writeByte( int value ){
294         int newSize = offset + 1;
295         if(newSize >= page.length) resizePage(newSize);
296
297         page[ offset++ ] = (byte)(value);
298     }
299
300     int readByte(){
301         return page[ offset++ ];
302     }
303
304     int readUnsignedByte(){
305         return page[ offset++ ] & 0xFF;
306     }
307
308     void writeBoolean( boolean value ){
309         int newSize = offset + 1;
310         if(newSize >= page.length) resizePage(newSize);
311
312         page[ offset++ ] = (byte)(value ? 1 : 0);
313     }
314
315     boolean readBoolean(){
316         return page[ offset++ ] != 0;
317     }
318
319     void writeShort( int value ){
320         int newSize = offset + 2;
321         if(newSize >= page.length) resizePage(newSize);
322
323         page[ offset++ ] = (byte)(value >> 8);
324         page[ offset++ ] = (byte)(value);
325     }
326
327     int readShort(){
328         return (page[ offset++ ] << 8) | (page[ offset++ ] & 0xFF);
329     }
330
331     void writeInt( int value ){
332         int newSize = offset + 4;
333         if(newSize >= page.length) resizePage(newSize);
334
335         page[ offset++ ] = (byte)(value >> 24);
336         page[ offset++ ] = (byte)(value >> 16);
337         page[ offset++ ] = (byte)(value >> 8);
338         page[ offset++ ] = (byte)(value);
339     }
340
341     int readInt(){
342         return ((page[ offset++ ]) << 24) |
343                 ((page[ offset++ ] & 0xFF) << 16) |
344                 ((page[ offset++ ] & 0xFF) << 8) |
345                 ((page[ offset++ ] & 0xFF));
346     }
347
348     void writeLong( long value ){
349         int newSize = offset + 8;
350         if(newSize >= page.length) resizePage(newSize);
351
352         page[ offset++ ] = (byte)(value >> 56);
353         page[ offset++ ] = (byte)(value >> 48);
354         page[ offset++ ] = (byte)(value >> 40);
355         page[ offset++ ] = (byte)(value >> 32);
356         page[ offset++ ] = (byte)(value >> 24);
357         page[ offset++ ] = (byte)(value >> 16);
358         page[ offset++ ] = (byte)(value >> 8);
359         page[ offset++ ] = (byte)(value);
360     }
361
362     long readLong(){
363         //return (((long)readInt()) << 32) | (readInt() & 0xFFFFFFFFL);
364
return ((long)(page[ offset++ ]) << 56) |
365                 ((long)(page[ offset++ ] & 0xFF) << 48) |
366                 ((long)(page[ offset++ ] & 0xFF) << 40) |
367                 ((long)(page[ offset++ ] & 0xFF) << 32) |
368                 ((long)(page[ offset++ ] & 0xFF) << 24) |
369                 ((page[ offset++ ] & 0xFF) << 16) |
370                 ((page[ offset++ ] & 0xFF) << 8) |
371                 ((page[ offset++ ] & 0xFF));
372     }
373
374     void writeDouble(double value){
375         writeLong( Double.doubleToLongBits(value) );
376     }
377
378     double readDouble(){
379         return Double.longBitsToDouble( readLong() );
380     }
381
382     void writeFloat(float value){
383         writeInt( Float.floatToIntBits(value) );
384     }
385
386     float readFloat(){
387         return Float.intBitsToFloat( readInt() );
388     }
389
390     void writeNumeric( MutableNumeric num){
391         writeByte( num.getInternalValue().length );
392         writeByte( num.getScale() );
393         writeByte( num.getSignum() );
394         for(int i=0; i<num.getInternalValue().length; i++){
395             writeInt( num.getInternalValue()[i] );
396         }
397     }
398
399     MutableNumeric readNumeric(){
400         int[] value = new int[ readByte() ];
401         int scale = readByte();
402         int signum = readByte();
403         for(int i=0; i<value.length; i++){
404             value[i] = readInt();
405         }
406         return new MutableNumeric( signum, value, scale );
407     }
408
409     void writeTimestamp( long ts){
410         writeLong( ts );
411     }
412
413     long readTimestamp(){
414         return readLong();
415     }
416
417     void writeTime( long time){
418         writeInt( (int)((time / 1000) % 86400) );
419     }
420
421     long readTime(){
422         return readInt() * 1000L;
423     }
424
425     void writeDate( long date){
426         writeInt( (int)(date / 86400000));
427     }
428
429     long readDate(){
430         return readInt() * 86400000L;
431     }
432
433     void writeSmallDateTime( long datetime){
434         writeInt( (int)(datetime / 60000));
435     }
436
437     long readSmallDateTime(){
438         return readInt() * 60000L;
439     }
440
441     void writeString( String JavaDoc strDaten ) throws SQLException JavaDoc{
442         writeString( strDaten, Short.MAX_VALUE, true );
443     }
444
445     void writeString( String JavaDoc strDaten, int lengthColumn, boolean varchar ) throws SQLException JavaDoc{
446         char[] daten = strDaten.toCharArray();
447         int length = daten.length;
448
449         if(lengthColumn < length){
450             throw Utils.createSQLException("String value to large for column.");
451         }
452         if(varchar) lengthColumn = length;
453         int newSize = offset + 2 + 2*lengthColumn;
454         if(newSize >= page.length) resizePage(newSize);
455
456         writeShort( lengthColumn );
457         writeChars( daten );
458         for(int i=length; i<lengthColumn; i++){
459             page[ offset++ ] = ' ';
460             page[ offset++ ] = 0;
461         }
462     }
463
464     String JavaDoc readString(){
465         int length = readShort();
466         return new String JavaDoc( readChars(length) );
467     }
468
469     void writeBytes(byte[] daten){
470         System.arraycopy( daten, 0, page, offset, daten.length);
471         offset += daten.length;
472     }
473
474     byte[] readBytes(int length){
475         byte[] daten = new byte[length];
476         System.arraycopy( page, offset, daten, 0, length);
477         offset += length;
478         return daten;
479     }
480
481     void writeBinary( byte[] daten, int lengthColumn, boolean varBinary ) throws SQLException JavaDoc{
482         int length = daten.length;
483
484         if(lengthColumn < length){
485             throw Utils.createSQLException("Binary value with length "+length+" to large for column with size "+lengthColumn+".");
486         }
487         if(varBinary) lengthColumn = length;
488         int newSize = offset + 2 + lengthColumn;
489         if(newSize >= page.length) resizePage(newSize);
490
491         page[ offset++ ] = (byte)(lengthColumn >> 8);
492         page[ offset++ ] = (byte)(lengthColumn);
493         writeBytes( daten );
494         if(!varBinary){
495             for(int i=length; i<lengthColumn; i++){
496                 page[ offset++ ] = 0;
497             }
498         }
499     }
500
501     byte[] readBinary(){
502         int length = readShort();
503         return readBytes(length);
504     }
505
506     void writeLongBinary( byte[] daten ) throws Exception JavaDoc{
507         StoreImpl store = table.getLobStore( ((TableStorePage)storePage).con, daten.length + 4, SQLTokenizer.LONGVARBINARY);
508         store.writeInt( daten.length );
509         store.writeBytes( daten );
510         writeLong( store.writeFinsh(null) );
511     }
512
513     byte[] readLongBinary() throws Exception JavaDoc{
514         long filePos = readLong();
515         StoreImpl store = table.getLobStore( ((TableStorePage)storePage).con, filePos, SQLTokenizer.SELECT );
516         return store.readBytes( store.readInt() );
517     }
518
519     void writeChars(char[] daten){
520         int length = daten.length;
521         for(int i=0; i<length; i++){
522             char c = daten[i];
523             page[ offset++ ] = (byte)(c);
524             page[ offset++ ] = (byte)(c >> 8);
525         }
526     }
527
528     char[] readChars(int length){
529         char[] daten = new char[length];
530         for(int i=0; i<length; i++){
531             daten[i] = (char)((page[ offset++ ] & 0xFF) | (page[ offset++ ] << 8));
532         }
533         return daten;
534     }
535
536     void writeLongString(String JavaDoc daten) throws Exception JavaDoc{
537         char[] chars = daten.toCharArray();
538         StoreImpl store = table.getLobStore( ((TableStorePage)storePage).con, chars.length * 2L + 4, SQLTokenizer.LONGVARBINARY);
539         store.writeInt( chars.length );
540         store.writeChars( chars );
541         writeLong( store.writeFinsh(null) );
542     }
543
544     String JavaDoc readLongString() throws Exception JavaDoc{
545         long filePos = readLong();
546         StoreImpl store = table.getLobStore( ((TableStorePage)storePage).con, filePos, SQLTokenizer.SELECT );
547         if(store == null) throw Utils.createSQLException("Lob Object was deleted.");
548         return new String JavaDoc(store.readChars( store.readInt() ) );
549     }
550     
551
552     void writeColumn( Table table, Column column ) throws Exception JavaDoc{
553         int newSize = offset + 25;
554         if(newSize >= page.length) resizePage(newSize);
555
556         writeByte ( column.getFlag() );
557         writeString ( column.getName() );
558         writeShort ( column.getDataType() );
559         writeInt ( column.getPrecision() );
560         writeByte ( column.getScale() );
561         offset += column.initAutoIncrement( table, storePage.raFile, filePos+offset);
562         String JavaDoc def = column.getDefaultDefinition();
563         writeBoolean( def == null );
564         if(def != null)
565             writeString ( column.getDefaultDefinition() );
566     }
567
568     
569     /**
570      * Read a single Column description on the current file offset.
571      * @param table The parent table of the column.
572      * @param tableFormatVersion the file version of the table.
573      * @return
574      * @throws Exception
575      */

576     Column readColumn(Table table, int tableFormatVersion) throws Exception JavaDoc{
577         Column column = new Column();
578         column.setFlag( readByte() );
579         column.setName( readString() );
580         column.setDataType( readShort() );
581         int precision;
582         if(tableFormatVersion == TableView.TABLE_VIEW_OLD_VERSION)
583             precision = readByte();
584         else
585             precision = readInt();
586         column.setPrecision( precision );
587         column.setScale( readByte() );
588         offset += column.initAutoIncrement( table, storePage.raFile, filePos+offset);
589         if(!readBoolean()){
590             String JavaDoc def = readString();
591             column.setDefaultValue( new SQLParser().parseExpression(def), def);
592         }
593         return column;
594     }
595  
596     
597     void copyValueFrom( StoreImpl store, int valueOffset, int length){
598         System.arraycopy( store.page, valueOffset, this.page, this.offset, length);
599         this.offset += length;
600     }
601
602     // hier wird Expression übergeben anstelle von Object, um später
603
// Optimierungen duchzuführen ohne Object für einfache Daten.
604
// Der Wert von offset muß stimmen.
605
void writeExpression( Expression expr, Column column) throws Exception JavaDoc{
606         boolean isNull = expr.isNull();
607         if(isNull && !column.isNullable()){
608             throw Utils.createSQLException("Null values are not valid for column '" + column.getName() + "'." );
609         }
610         int dataType = column.getDataType();
611         if(isNull){
612             writeBoolean(true); //true - is null
613
switch(dataType){
614                 case SQLTokenizer.BIT:
615                 case SQLTokenizer.BOOLEAN:
616                 case SQLTokenizer.TINYINT:
617                     offset++;
618                     break;
619                 case SQLTokenizer.SMALLINT:
620                 case SQLTokenizer.BINARY:
621                 case SQLTokenizer.VARBINARY:
622                 case SQLTokenizer.CHAR:
623                 case SQLTokenizer.NCHAR:
624                 case SQLTokenizer.VARCHAR:
625                 case SQLTokenizer.NVARCHAR:
626                     offset += 2;
627                     break;
628                 case SQLTokenizer.INT:
629                 case SQLTokenizer.REAL:
630                 case SQLTokenizer.SMALLMONEY:
631                 case SQLTokenizer.TIME:
632                 case SQLTokenizer.DATE:
633                 case SQLTokenizer.SMALLDATETIME:
634                     offset += 4;
635                     break;
636                 case SQLTokenizer.BIGINT:
637                 case SQLTokenizer.FLOAT:
638                 case SQLTokenizer.DOUBLE:
639                 case SQLTokenizer.MONEY:
640                 case SQLTokenizer.JAVA_OBJECT:
641                 case SQLTokenizer.LONGVARBINARY:
642                 case SQLTokenizer.BLOB:
643                 case SQLTokenizer.CLOB:
644                 case SQLTokenizer.NCLOB:
645                 case SQLTokenizer.LONGNVARCHAR:
646                 case SQLTokenizer.LONGVARCHAR:
647                 case SQLTokenizer.TIMESTAMP:
648                     offset += 8;
649                     break;
650                 case SQLTokenizer.UNIQUEIDENTIFIER:
651                     offset += 16;
652                     break;
653                 case SQLTokenizer.NUMERIC:
654                 case SQLTokenizer.DECIMAL:
655                     offset += 3;
656                     break;
657                 default: throw new Error JavaDoc();
658             }
659             return;
660         }
661         writeBoolean(false); // false - is not null
662
column.setNewAutoIncrementValue(expr);
663         switch(dataType){
664             case SQLTokenizer.BIT:
665             case SQLTokenizer.BOOLEAN:
666                     writeBoolean( expr.getBoolean() );
667                     break;
668             case SQLTokenizer.BINARY:
669             case SQLTokenizer.VARBINARY:
670                     writeBinary( expr.getBytes(), column.getPrecision(), dataType != SQLTokenizer.BINARY );
671                     break;
672             case SQLTokenizer.TINYINT:
673                     writeByte( expr.getInt() );
674                     break;
675             case SQLTokenizer.SMALLINT:
676                     writeShort( expr.getInt() );
677                     break;
678             case SQLTokenizer.INT:
679                     writeInt( expr.getInt() );
680                     break;
681             case SQLTokenizer.BIGINT:
682                     writeLong( expr.getLong() );
683                     break;
684             case SQLTokenizer.REAL:
685                     writeFloat( expr.getFloat() );
686                     break;
687             case SQLTokenizer.FLOAT:
688             case SQLTokenizer.DOUBLE:
689                     writeDouble( expr.getDouble() );
690                     break;
691             case SQLTokenizer.MONEY:
692                     writeLong( expr.getMoney() );
693                     break;
694             case SQLTokenizer.SMALLMONEY:
695                     writeInt( (int)expr.getMoney() );
696                     break;
697             case SQLTokenizer.NUMERIC:
698             case SQLTokenizer.DECIMAL:
699                     MutableNumeric numeric = expr.getNumeric();
700                     numeric.setScale( column.getScale() );
701                     writeNumeric( numeric );
702                     break;
703             case SQLTokenizer.CHAR:
704             case SQLTokenizer.NCHAR:
705                     writeString( expr.getString(), column.getDisplaySize(), false );
706                     break;
707             case SQLTokenizer.VARCHAR:
708             case SQLTokenizer.NVARCHAR:
709                     writeString( expr.getString(), column.getDisplaySize(), true );
710                     break;
711             case SQLTokenizer.CLOB:
712             case SQLTokenizer.NCLOB:
713             case SQLTokenizer.LONGNVARCHAR:
714             case SQLTokenizer.LONGVARCHAR:
715                     writeLongString( expr.getString() );
716                     break;
717             case SQLTokenizer.JAVA_OBJECT:
718                     // Fixme ein MemoryStream könnte schneller sein
719
ByteArrayOutputStream baos = new ByteArrayOutputStream();
720                     ObjectOutputStream oos = new ObjectOutputStream(baos);
721                     oos.writeObject( expr.getObject() );
722                     writeLongBinary( baos.toByteArray() );
723                     break;
724             case SQLTokenizer.LONGVARBINARY:
725             case SQLTokenizer.BLOB:
726                     writeLongBinary( expr.getBytes() );
727                     break;
728             case SQLTokenizer.TIMESTAMP:
729                     writeTimestamp( expr.getLong() );
730                     break;
731             case SQLTokenizer.TIME:
732                     writeTime( expr.getLong() );
733                     break;
734             case SQLTokenizer.DATE:
735                     writeDate( expr.getLong() );
736                     break;
737             case SQLTokenizer.SMALLDATETIME:
738                     writeSmallDateTime( expr.getLong() );
739                     break;
740             case SQLTokenizer.UNIQUEIDENTIFIER:
741                     switch(expr.getDataType()){
742                     case SQLTokenizer.UNIQUEIDENTIFIER:
743                     case SQLTokenizer.BINARY:
744                     case SQLTokenizer.VARBINARY:
745                     case SQLTokenizer.LONGVARBINARY:
746                     case SQLTokenizer.BLOB:
747                         byte[] bytes = expr.getBytes();
748                         if(bytes.length != 16) throw Utils.createSQLException("Invalid byte array size:"+bytes.length);
749                         writeBytes( bytes );
750                     default:
751                         writeBytes( Utils.unique2bytes(expr.getString()) );
752                     }
753                     break;
754             default: throw new Error JavaDoc(String.valueOf(column.getDataType()));
755         }
756     }
757
758     boolean isNull(int offset){
759         return page[ offset ] != 0;
760     }
761
762     // wird für ResultSet.getBoolean() verwendet
763
boolean getBoolean( int offset, int dataType) throws Exception JavaDoc{
764         this.offset = offset;
765         if(readBoolean()) return false;
766         switch(dataType){
767             case SQLTokenizer.BIT:
768             case SQLTokenizer.BOOLEAN:
769                     return readBoolean();
770             case SQLTokenizer.BINARY:
771             case SQLTokenizer.VARBINARY:
772                     return Utils.bytes2int( readBinary() ) != 0;
773             case SQLTokenizer.TINYINT:
774                     return readUnsignedByte() != 0;
775             case SQLTokenizer.SMALLINT:
776                     return readShort() != 0;
777             case SQLTokenizer.INT:
778                     return readInt() != 0;
779             case SQLTokenizer.BIGINT:
780                     return readLong() != 0;
781             case SQLTokenizer.REAL:
782                     return readFloat() != 0;
783             case SQLTokenizer.FLOAT:
784             case SQLTokenizer.DOUBLE:
785                     return readDouble() != 0;
786             case SQLTokenizer.MONEY:
787                     return readLong() != 0;
788             case SQLTokenizer.SMALLMONEY:
789                     return readInt() != 0;
790             case SQLTokenizer.NUMERIC:
791             case SQLTokenizer.DECIMAL:
792                     return readNumeric().getSignum() != 0;
793             case SQLTokenizer.CHAR:
794             case SQLTokenizer.NCHAR:
795             case SQLTokenizer.VARCHAR:
796             case SQLTokenizer.NVARCHAR:
797                     return Utils.string2boolean( readString() );
798             case SQLTokenizer.CLOB:
799             case SQLTokenizer.NCLOB:
800             case SQLTokenizer.LONGNVARCHAR:
801             case SQLTokenizer.LONGVARCHAR:
802                     return Utils.string2boolean( readLongString() );
803             case SQLTokenizer.JAVA_OBJECT:
804                     ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
805                     ObjectInputStream ois = new ObjectInputStream(bais);
806                     return Utils.string2boolean( ois.readObject().toString() );
807             case SQLTokenizer.LONGVARBINARY:
808             case SQLTokenizer.BLOB:
809                     return Utils.bytes2int( readLongBinary() ) != 0;
810             case SQLTokenizer.TIMESTAMP:
811                     return readTimestamp() != 0;
812             case SQLTokenizer.TIME:
813                     return readTime() != 0;
814             case SQLTokenizer.DATE:
815                     return readDate() != 0;
816             case SQLTokenizer.SMALLDATETIME:
817                     return readSmallDateTime() != 0;
818             case SQLTokenizer.UNIQUEIDENTIFIER:
819                 return false;
820             default: throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a BOOLEAN value.");
821         }
822     }
823
824     // wird für ResultSet.getInt() verwendet
825
int getInt( int offset, int dataType) throws Exception JavaDoc{
826         this.offset = offset;
827         if(readBoolean()) return 0;
828         switch(dataType){
829             case SQLTokenizer.BIT:
830             case SQLTokenizer.BOOLEAN:
831                     return readBoolean() ? 1 : 0;
832             case SQLTokenizer.BINARY:
833             case SQLTokenizer.VARBINARY:
834                     return Utils.bytes2int( readBinary() );
835             case SQLTokenizer.TINYINT:
836                     return readUnsignedByte();
837             case SQLTokenizer.SMALLINT:
838                     return readShort();
839             case SQLTokenizer.INT:
840                     return readInt();
841             case SQLTokenizer.BIGINT:
842                     return (int)readLong();
843             case SQLTokenizer.REAL:
844                     return (int)readFloat();
845             case SQLTokenizer.FLOAT:
846             case SQLTokenizer.DOUBLE:
847                     return (int)readDouble();
848             case SQLTokenizer.MONEY:
849                     return (int)(readLong() / 10000);
850             case SQLTokenizer.SMALLMONEY:
851                     return readInt() / 10000;
852             case SQLTokenizer.NUMERIC:
853             case SQLTokenizer.DECIMAL:
854                     return readNumeric().intValue();
855             case SQLTokenizer.CHAR:
856             case SQLTokenizer.NCHAR:
857             case SQLTokenizer.VARCHAR:
858             case SQLTokenizer.NVARCHAR:
859                     return Integer.parseInt( readString() );
860             case SQLTokenizer.CLOB:
861             case SQLTokenizer.NCLOB:
862             case SQLTokenizer.LONGNVARCHAR:
863             case SQLTokenizer.LONGVARCHAR:
864                     return Integer.parseInt( readLongString() );
865             case SQLTokenizer.JAVA_OBJECT:
866                     ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
867                     ObjectInputStream ois = new ObjectInputStream(bais);
868                     return ExpressionValue.getInt(ois.readObject().toString(), SQLTokenizer.VARCHAR);
869             case SQLTokenizer.LONGVARBINARY:
870             case SQLTokenizer.BLOB:
871                     return Utils.bytes2int( readLongBinary() );
872             case SQLTokenizer.TIMESTAMP:
873                     return (int)readTimestamp();
874             case SQLTokenizer.TIME:
875                     return (int)readTime();
876             case SQLTokenizer.DATE:
877                     return (int)readDate();
878             case SQLTokenizer.SMALLDATETIME:
879                     return (int)readSmallDateTime();
880             default: throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a INT value.");
881         }
882     }
883
884     // wird für ResultSet.getLong() verwendet
885
long getLong( int offset, int dataType) throws Exception JavaDoc{
886         this.offset = offset;
887         if(readBoolean()) return 0;
888         switch(dataType){
889             case SQLTokenizer.BIT:
890             case SQLTokenizer.BOOLEAN:
891                     return readBoolean() ? 1 : 0;
892             case SQLTokenizer.BINARY:
893             case SQLTokenizer.VARBINARY:
894                     return Utils.bytes2long( readBinary() );
895             case SQLTokenizer.TINYINT:
896                     return readUnsignedByte();
897             case SQLTokenizer.SMALLINT:
898                     return readShort();
899             case SQLTokenizer.INT:
900                     return readInt();
901             case SQLTokenizer.BIGINT:
902                     return readLong();
903             case SQLTokenizer.REAL:
904                     return (long)readFloat();
905             case SQLTokenizer.FLOAT:
906             case SQLTokenizer.DOUBLE:
907                     return (long)readDouble();
908             case SQLTokenizer.MONEY:
909                     return readLong() / 10000;
910             case SQLTokenizer.SMALLMONEY:
911                     return readInt() / 10000;
912             case SQLTokenizer.NUMERIC:
913             case SQLTokenizer.DECIMAL:
914                     return readNumeric().longValue();
915             case SQLTokenizer.CHAR:
916             case SQLTokenizer.NCHAR:
917             case SQLTokenizer.VARCHAR:
918             case SQLTokenizer.NVARCHAR:
919                     return Long.parseLong( readString() );
920             case SQLTokenizer.CLOB:
921             case SQLTokenizer.NCLOB:
922             case SQLTokenizer.LONGNVARCHAR:
923             case SQLTokenizer.LONGVARCHAR:
924                     return Long.parseLong( readLongString() );
925             case SQLTokenizer.JAVA_OBJECT:
926                     ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
927                     ObjectInputStream ois = new ObjectInputStream(bais);
928                     return ExpressionValue.getLong( ois.readObject().toString(), SQLTokenizer.VARCHAR );
929             case SQLTokenizer.LONGVARBINARY:
930             case SQLTokenizer.BLOB:
931                     return Utils.bytes2long( readLongBinary() );
932             case SQLTokenizer.TIMESTAMP:
933                     return readTimestamp();
934             case SQLTokenizer.TIME:
935                     return readTime();
936             case SQLTokenizer.DATE:
937                     return readDate();
938             case SQLTokenizer.SMALLDATETIME:
939                     return readSmallDateTime();
940             default: throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a BIGINT value.");
941         }
942     }
943
944     // wird für ResultSet.getFloat() verwendet
945
float getFloat( int offset, int dataType) throws Exception JavaDoc{
946         this.offset = offset;
947         if(readBoolean()) return 0;
948         switch(dataType){
949             case SQLTokenizer.BIT:
950             case SQLTokenizer.BOOLEAN:
951                     return readBoolean() ? 1 : 0;
952             case SQLTokenizer.BINARY:
953             case SQLTokenizer.VARBINARY:
954                     return Utils.bytes2float( readBinary() );
955             case SQLTokenizer.TINYINT:
956                     return readUnsignedByte();
957             case SQLTokenizer.SMALLINT:
958                     return readShort();
959             case SQLTokenizer.INT:
960                     return readInt();
961             case SQLTokenizer.BIGINT:
962                     return readLong();
963             case SQLTokenizer.REAL:
964                     return readFloat();
965             case SQLTokenizer.FLOAT:
966             case SQLTokenizer.DOUBLE:
967                     return (float)readDouble();
968             case SQLTokenizer.MONEY:
969                     return readLong() / (float)10000.0;
970             case SQLTokenizer.SMALLMONEY:
971                     return readInt() / (float)10000.0;
972             case SQLTokenizer.NUMERIC:
973             case SQLTokenizer.DECIMAL:
974                     return readNumeric().floatValue();
975             case SQLTokenizer.CHAR:
976             case SQLTokenizer.NCHAR:
977             case SQLTokenizer.VARCHAR:
978             case SQLTokenizer.NVARCHAR:
979                     return Float.parseFloat( readString() );
980             case SQLTokenizer.CLOB:
981             case SQLTokenizer.NCLOB:
982             case SQLTokenizer.LONGNVARCHAR:
983             case SQLTokenizer.LONGVARCHAR:
984                     return Float.parseFloat( readLongString() );
985             case SQLTokenizer.JAVA_OBJECT:
986                     ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
987                     ObjectInputStream ois = new ObjectInputStream(bais);
988                     return Float.parseFloat( ois.readObject().toString() );
989             case SQLTokenizer.LONGVARBINARY:
990             case SQLTokenizer.BLOB:
991                     return Utils.bytes2float( readLongBinary() );
992             case SQLTokenizer.TIMESTAMP:
993                     return readTimestamp();
994             case SQLTokenizer.TIME:
995                     return readTime();
996             case SQLTokenizer.DATE:
997                     return readDate();
998             case SQLTokenizer.SMALLDATETIME:
999                     return readSmallDateTime();
1000            default: throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a REAL value.");
1001        }
1002    }
1003
1004    // wird für ResultSet.getDouble() verwendet
1005
double getDouble( int offset, int dataType) throws Exception JavaDoc{
1006        this.offset = offset;
1007        if(readBoolean()) return 0;
1008        switch(dataType){
1009            case SQLTokenizer.BIT:
1010            case SQLTokenizer.BOOLEAN:
1011                    return readBoolean() ? 1 : 0;
1012            case SQLTokenizer.BINARY:
1013            case SQLTokenizer.VARBINARY:
1014                    return Utils.bytes2double( readBinary() );
1015            case SQLTokenizer.TINYINT:
1016                    return readUnsignedByte();
1017            case SQLTokenizer.SMALLINT:
1018                    return readShort();
1019            case SQLTokenizer.INT:
1020                    return readInt();
1021            case SQLTokenizer.BIGINT:
1022                    return readLong();
1023            case SQLTokenizer.REAL:
1024                    return readFloat();
1025            case SQLTokenizer.FLOAT:
1026            case SQLTokenizer.DOUBLE:
1027                    return readDouble();
1028            case SQLTokenizer.MONEY:
1029                    return readLong() / 10000.0;
1030            case SQLTokenizer.SMALLMONEY:
1031                    return readInt() / 10000.0;
1032            case SQLTokenizer.NUMERIC:
1033            case SQLTokenizer.DECIMAL:
1034                    return readNumeric().doubleValue();
1035            case SQLTokenizer.CHAR:
1036            case SQLTokenizer.NCHAR:
1037            case SQLTokenizer.VARCHAR:
1038            case SQLTokenizer.NVARCHAR:
1039                    return Double.parseDouble( readString() );
1040            case SQLTokenizer.CLOB:
1041            case SQLTokenizer.NCLOB:
1042            case SQLTokenizer.LONGNVARCHAR:
1043            case SQLTokenizer.LONGVARCHAR:
1044                    return Double.parseDouble( readLongString() );
1045            case SQLTokenizer.JAVA_OBJECT:
1046                    ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
1047                    ObjectInputStream ois = new ObjectInputStream(bais);
1048                    return Double.parseDouble( ois.readObject().toString() );
1049            case SQLTokenizer.LONGVARBINARY:
1050            case SQLTokenizer.BLOB:
1051                    return Utils.bytes2double( readLongBinary() );
1052            case SQLTokenizer.TIMESTAMP:
1053                    return readTimestamp();
1054            case SQLTokenizer.TIME:
1055                    return readTime();
1056            case SQLTokenizer.DATE:
1057                    return readDate();
1058            case SQLTokenizer.SMALLDATETIME:
1059                    return readSmallDateTime();
1060            default: throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a DOUBLE value.");
1061        }
1062    }
1063
1064    // wird zum schnelleren Rechnen verwendet
1065
long getMoney( int offset, int dataType) throws Exception JavaDoc{
1066        this.offset = offset;
1067        if(readBoolean()) return 0;
1068        switch(dataType){
1069            case SQLTokenizer.BIT:
1070            case SQLTokenizer.BOOLEAN:
1071                    return readBoolean() ? 10000 : 0;
1072            case SQLTokenizer.BINARY:
1073            case SQLTokenizer.VARBINARY:
1074                    return (long)(Utils.bytes2double( readBinary() ) * 10000L);
1075            case SQLTokenizer.TINYINT:
1076                    return readUnsignedByte() * 10000L;
1077            case SQLTokenizer.SMALLINT:
1078                    return readShort() * 10000L;
1079            case SQLTokenizer.INT:
1080                    return readInt() * 10000L;
1081            case SQLTokenizer.BIGINT:
1082                    return readLong() * 10000L;
1083            case SQLTokenizer.REAL:
1084                    return (long)(readFloat() * 10000L);
1085            case SQLTokenizer.FLOAT:
1086            case SQLTokenizer.DOUBLE:
1087                    return (long)(readDouble() * 10000L);
1088            case SQLTokenizer.MONEY:
1089                    return readLong();
1090            case SQLTokenizer.SMALLMONEY:
1091                    return readInt();
1092            case SQLTokenizer.NUMERIC:
1093            case SQLTokenizer.DECIMAL:
1094                    return (long)(readNumeric().doubleValue() * 10000L);
1095            case SQLTokenizer.CHAR:
1096            case SQLTokenizer.NCHAR:
1097            case SQLTokenizer.VARCHAR:
1098            case SQLTokenizer.NVARCHAR:
1099                    return Money.parseMoney( readString() );
1100            case SQLTokenizer.CLOB:
1101            case SQLTokenizer.NCLOB:
1102            case SQLTokenizer.LONGNVARCHAR:
1103            case SQLTokenizer.LONGVARCHAR:
1104                    return Money.parseMoney( readLongString() );
1105            case SQLTokenizer.JAVA_OBJECT:
1106                    ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
1107                    ObjectInputStream ois = new ObjectInputStream(bais);
1108                    return Money.parseMoney( ois.readObject().toString() );
1109            case SQLTokenizer.LONGVARBINARY:
1110            case SQLTokenizer.BLOB:
1111                    return (long)(Utils.bytes2double( readLongBinary() ) * 10000L);
1112            case SQLTokenizer.TIMESTAMP:
1113            case SQLTokenizer.TIME:
1114            case SQLTokenizer.DATE:
1115            case SQLTokenizer.SMALLDATETIME:
1116                    throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a MONEY value.");
1117            default: throw new Error JavaDoc();
1118        }
1119    }
1120
1121    // wird für ResultSet.getBigDecimal() verwendet
1122
MutableNumeric getNumeric( int offset, int dataType) throws Exception JavaDoc{
1123        this.offset = offset;
1124        if(readBoolean()) return null;
1125        switch(dataType){
1126            case SQLTokenizer.BIT:
1127            case SQLTokenizer.BOOLEAN:
1128                    return readBoolean() ? new MutableNumeric(1) : new MutableNumeric(0);
1129            case SQLTokenizer.BINARY:
1130            case SQLTokenizer.VARBINARY:
1131                    return new MutableNumeric(Utils.bytes2double( readBinary() ));
1132            case SQLTokenizer.TINYINT:
1133                    return new MutableNumeric(readUnsignedByte());
1134            case SQLTokenizer.SMALLINT:
1135                    return new MutableNumeric(readShort());
1136            case SQLTokenizer.INT:
1137                    return new MutableNumeric(readInt());
1138            case SQLTokenizer.BIGINT:
1139                    return new MutableNumeric(readLong());
1140            case SQLTokenizer.REAL:
1141                    return new MutableNumeric(readFloat());
1142            case SQLTokenizer.FLOAT:
1143            case SQLTokenizer.DOUBLE:
1144                    return new MutableNumeric(readDouble());
1145            case SQLTokenizer.MONEY:
1146                    return new MutableNumeric( readLong(), 4);
1147            case SQLTokenizer.SMALLMONEY:
1148                    return new MutableNumeric( readInt(), 4);
1149            case SQLTokenizer.NUMERIC:
1150            case SQLTokenizer.DECIMAL:
1151                    return readNumeric();
1152            case SQLTokenizer.CHAR:
1153            case SQLTokenizer.NCHAR:
1154            case SQLTokenizer.VARCHAR:
1155            case SQLTokenizer.NVARCHAR:
1156                    return new MutableNumeric( readString() );
1157            case SQLTokenizer.CLOB:
1158            case SQLTokenizer.NCLOB:
1159            case SQLTokenizer.LONGNVARCHAR:
1160            case SQLTokenizer.LONGVARCHAR:
1161                    return new MutableNumeric( readLongString() );
1162            case SQLTokenizer.JAVA_OBJECT:
1163                    ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
1164                    ObjectInputStream ois = new ObjectInputStream(bais);
1165                    return new MutableNumeric( ois.readObject().toString() );
1166            case SQLTokenizer.LONGVARBINARY:
1167            case SQLTokenizer.BLOB:
1168                    return new MutableNumeric( Utils.bytes2double( readLongBinary() ) );
1169            case SQLTokenizer.TIMESTAMP:
1170            case SQLTokenizer.TIME:
1171            case SQLTokenizer.DATE:
1172            case SQLTokenizer.SMALLDATETIME:
1173                    throw Utils.createSQLException("Cannot convert a " + SQLTokenizer.getKeyWord(dataType) + " value to a NUMERIC value.");
1174            default: throw new Error JavaDoc();
1175        }
1176    }
1177
1178
1179
1180    // wird für ResultSet.getObject() verwendet
1181
Object JavaDoc getObject( int offset, int dataType) throws Exception JavaDoc{
1182        this.offset = offset;
1183        if(readBoolean()) return null;
1184        switch(dataType){
1185            case SQLTokenizer.BIT:
1186            case SQLTokenizer.BOOLEAN:
1187                    return readBoolean() ? Boolean.TRUE : Boolean.FALSE;
1188            case SQLTokenizer.BINARY:
1189            case SQLTokenizer.VARBINARY:
1190                    return readBinary();
1191            case SQLTokenizer.TINYINT:
1192                    return Utils.getInteger( readUnsignedByte() );
1193            case SQLTokenizer.SMALLINT:
1194                    return Utils.getInteger( readShort() );
1195            case SQLTokenizer.INT:
1196                    return Utils.getInteger(readInt());
1197            case SQLTokenizer.BIGINT:
1198                    return new Long JavaDoc(readLong());
1199            case SQLTokenizer.REAL:
1200                    return new Float JavaDoc( readFloat() );
1201            case SQLTokenizer.FLOAT:
1202            case SQLTokenizer.DOUBLE:
1203                    return new Double JavaDoc( readDouble() );
1204            case SQLTokenizer.MONEY:
1205                    return Money.createFromUnscaledValue(readLong());
1206            case SQLTokenizer.SMALLMONEY:
1207                    return Money.createFromUnscaledValue(readInt());
1208            case SQLTokenizer.NUMERIC:
1209            case SQLTokenizer.DECIMAL:
1210                    return readNumeric();
1211            case SQLTokenizer.CHAR:
1212            case SQLTokenizer.NCHAR:
1213            case SQLTokenizer.VARCHAR:
1214            case SQLTokenizer.NVARCHAR:
1215                    return readString();
1216            case SQLTokenizer.CLOB:
1217            case SQLTokenizer.NCLOB:
1218            case SQLTokenizer.LONGNVARCHAR:
1219            case SQLTokenizer.LONGVARCHAR:
1220                    return readLongString();
1221            case SQLTokenizer.JAVA_OBJECT:
1222                    ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
1223                    ObjectInputStream ois = new ObjectInputStream(bais);
1224                    return ois.readObject();
1225            case SQLTokenizer.LONGVARBINARY:
1226            case SQLTokenizer.BLOB:
1227                    return readLongBinary();
1228            case SQLTokenizer.TIMESTAMP:
1229                    return new DateTime( readTimestamp(), SQLTokenizer.TIMESTAMP );
1230            case SQLTokenizer.TIME:
1231                    return new DateTime( readTime(), SQLTokenizer.TIME );
1232            case SQLTokenizer.DATE:
1233                    return new DateTime( readDate(), SQLTokenizer.DATE );
1234            case SQLTokenizer.SMALLDATETIME:
1235                    return new DateTime( readSmallDateTime(), SQLTokenizer.TIMESTAMP );
1236            case SQLTokenizer.UNIQUEIDENTIFIER:
1237                    return Utils.bytes2unique( page, this.offset);
1238            default: throw new Error JavaDoc();
1239        }
1240    }
1241
1242    // wird für ResultSet.getString() verwendet
1243
String JavaDoc getString( int offset, int dataType) throws Exception JavaDoc{
1244        this.offset = offset;
1245        if(readBoolean()) return null;
1246        switch(dataType){
1247            case SQLTokenizer.BIT:
1248                    return readBoolean() ? "1" : "0";
1249            case SQLTokenizer.BOOLEAN:
1250                    return String.valueOf( readBoolean() );
1251            case SQLTokenizer.BINARY:
1252            case SQLTokenizer.VARBINARY:
1253                    return Utils.bytes2hex( readBinary() );
1254            case SQLTokenizer.TINYINT:
1255                    return String.valueOf( readUnsignedByte() );
1256            case SQLTokenizer.SMALLINT:
1257                    return String.valueOf( readShort() );
1258            case SQLTokenizer.INT:
1259                    return String.valueOf( readInt() );
1260            case SQLTokenizer.BIGINT:
1261                    return String.valueOf( readLong() );
1262            case SQLTokenizer.REAL:
1263                    return String.valueOf( readFloat() );
1264            case SQLTokenizer.FLOAT:
1265            case SQLTokenizer.DOUBLE:
1266                    return String.valueOf( readDouble() );
1267            case SQLTokenizer.MONEY:
1268                    return Money.createFromUnscaledValue( readLong() ).toString();
1269            case SQLTokenizer.SMALLMONEY:
1270                    return Money.createFromUnscaledValue( readInt() ).toString();
1271            case SQLTokenizer.NUMERIC:
1272            case SQLTokenizer.DECIMAL:
1273                    return readNumeric().toString();
1274            case SQLTokenizer.CHAR:
1275            case SQLTokenizer.NCHAR:
1276            case SQLTokenizer.VARCHAR:
1277            case SQLTokenizer.NVARCHAR:
1278                    return readString();
1279            case SQLTokenizer.CLOB:
1280            case SQLTokenizer.NCLOB:
1281            case SQLTokenizer.LONGNVARCHAR:
1282            case SQLTokenizer.LONGVARCHAR:
1283                    return readLongString();
1284            case SQLTokenizer.JAVA_OBJECT:
1285                    ByteArrayInputStream bais = new ByteArrayInputStream(readLongBinary());
1286                    ObjectInputStream ois = new ObjectInputStream(bais);
1287                    return ois.readObject().toString();
1288            case SQLTokenizer.LONGVARBINARY:
1289            case SQLTokenizer.BLOB:
1290                    return Utils.bytes2hex( readLongBinary() );
1291            case SQLTokenizer.TIMESTAMP:
1292                    return new DateTime( readTimestamp(), SQLTokenizer.TIMESTAMP ).toString();
1293            case SQLTokenizer.TIME:
1294                    return new DateTime( readTime(), SQLTokenizer.TIME ).toString();
1295            case SQLTokenizer.DATE:
1296                    return new DateTime( readDate(), SQLTokenizer.DATE ).toString();
1297            case SQLTokenizer.SMALLDATETIME:
1298                    return new DateTime( readSmallDateTime(), SQLTokenizer.TIMESTAMP ).toString();
1299            case SQLTokenizer.UNIQUEIDENTIFIER:
1300                    return Utils.bytes2unique( page, this.offset);
1301            default: throw new Error JavaDoc();
1302        }
1303    }
1304
1305    // wird für ResultSet.getBytes() verwendet
1306
byte[] getBytes( int offset, int dataType) throws Exception JavaDoc{
1307        this.offset = offset;
1308        if(readBoolean()) return null;
1309        switch(dataType){
1310            case SQLTokenizer.BINARY:
1311            case SQLTokenizer.VARBINARY:
1312                    return readBinary();
1313            case SQLTokenizer.TINYINT:
1314            case SQLTokenizer.BIT:
1315            case SQLTokenizer.BOOLEAN:
1316                    byte[] bytes = new byte[1];
1317                    System.arraycopy( page, offset, bytes, 0, bytes.length);
1318                    return bytes;
1319            case SQLTokenizer.SMALLINT:
1320                    bytes = new byte[2];
1321                    System.arraycopy( page, offset, bytes, 0, bytes.length);
1322                    return bytes;
1323            case SQLTokenizer.INT:
1324            case SQLTokenizer.REAL:
1325            case SQLTokenizer.SMALLMONEY:
1326            case SQLTokenizer.TIME:
1327            case SQLTokenizer.DATE:
1328            case SQLTokenizer.SMALLDATETIME:
1329                    bytes = new byte[4];
1330                    System.arraycopy( page, offset, bytes, 0, bytes.length);
1331                    return bytes;
1332            case SQLTokenizer.BIGINT:
1333            case SQLTokenizer.FLOAT:
1334            case SQLTokenizer.DOUBLE:
1335            case SQLTokenizer.MONEY:
1336            case SQLTokenizer.TIMESTAMP:
1337                    bytes = new byte[8];
1338                    System.arraycopy( page, offset, bytes, 0, bytes.length);
1339                    return bytes;
1340            case SQLTokenizer.NUMERIC:
1341            case SQLTokenizer.DECIMAL:
1342                    return readNumeric().toByteArray();
1343            case SQLTokenizer.CHAR:
1344            case SQLTokenizer.NCHAR:
1345            case SQLTokenizer.VARCHAR:
1346            case SQLTokenizer.NVARCHAR:
1347                    return readString().getBytes();
1348            case SQLTokenizer.CLOB:
1349            case SQLTokenizer.NCLOB:
1350            case SQLTokenizer.LONGNVARCHAR:
1351            case SQLTokenizer.LONGVARCHAR:
1352                    return readLongString().getBytes();
1353            case SQLTokenizer.JAVA_OBJECT:
1354            case SQLTokenizer.LONGVARBINARY:
1355            case SQLTokenizer.BLOB:
1356                    return readLongBinary();
1357            case SQLTokenizer.UNIQUEIDENTIFIER:
1358                    bytes = new byte[16];
1359                    System.arraycopy( page, offset, bytes, 0, bytes.length);
1360                    return bytes;
1361            default: throw new Error JavaDoc();
1362        }
1363    }
1364
1365    void scanObjectOffsets( int[] offsets, int dataTypes[] ){
1366        offset = PAGE_CONTROL_SIZE;
1367        for(int i=0; i<offsets.length; i++){
1368            offsets[i] = offset;
1369            boolean isNull = readBoolean(); // für isNull
1370
switch(dataTypes[i]){
1371                case SQLTokenizer.BIT:
1372                case SQLTokenizer.BOOLEAN:
1373                case SQLTokenizer.TINYINT:
1374                    offset++;
1375                    break;
1376                case SQLTokenizer.SMALLINT:
1377                    offset += 2;
1378                    break;
1379                case SQLTokenizer.INT:
1380                case SQLTokenizer.REAL:
1381                case SQLTokenizer.SMALLMONEY:
1382                case SQLTokenizer.TIME:
1383                case SQLTokenizer.DATE:
1384                case SQLTokenizer.SMALLDATETIME:
1385                    offset += 4;
1386                    break;
1387                case SQLTokenizer.BIGINT:
1388                case SQLTokenizer.FLOAT:
1389                case SQLTokenizer.DOUBLE:
1390                case SQLTokenizer.MONEY:
1391                case SQLTokenizer.JAVA_OBJECT:
1392                case SQLTokenizer.LONGVARBINARY:
1393                case SQLTokenizer.BLOB:
1394                case SQLTokenizer.CLOB:
1395                case SQLTokenizer.NCLOB:
1396                case SQLTokenizer.LONGNVARCHAR:
1397                case SQLTokenizer.LONGVARCHAR:
1398                case SQLTokenizer.TIMESTAMP:
1399                    offset += 8;
1400                    break;
1401                case SQLTokenizer.BINARY:
1402                case SQLTokenizer.VARBINARY:
1403                    int count = readShort();
1404                    if(!isNull) offset += count; // nicht += verwenden, weil readShort offset verändert
1405
break;
1406                case SQLTokenizer.NUMERIC:
1407                case SQLTokenizer.DECIMAL:
1408                    count = readByte();
1409                    offset += 2;
1410                    if(!isNull) offset += count*4;
1411                    break;
1412                case SQLTokenizer.CHAR:
1413                case SQLTokenizer.NCHAR:
1414                case SQLTokenizer.VARCHAR:
1415                case SQLTokenizer.NVARCHAR:
1416                    count = readShort();
1417                    if(!isNull) offset += count << 1; // nicht += verwenden, weil readShort offset verändert
1418
break;
1419                case SQLTokenizer.UNIQUEIDENTIFIER:
1420                    offset += 16;
1421                    break;
1422                default: throw new Error JavaDoc(String.valueOf( dataTypes[i] ) );
1423            }
1424        }
1425    }
1426
1427    void deleteRow(SSConnection con) throws SQLException JavaDoc{
1428        status = DELETED;
1429        type = SQLTokenizer.DELETE;
1430        createWriteLock();
1431        writeFinsh(con);
1432    }
1433    
1434    
1435    StorePageLink getLink(){
1436        return ((TableStorePageInsert)storePage).getLink();
1437    }
1438}
Popular Tags