EMMA Coverage Report (generated Wed Jun 28 19:54:35 CEST 2006)
[all classes][smallsql.database]

COVERAGE SUMMARY FOR SOURCE FILE [StoreImpl.java]

nameclass, %method, %block, %line, %
StoreImpl.java100% (1/1)100% (71/71)81%  (2688/3307)84%  (542,1/643)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class StoreImpl100% (1/1)100% (71/71)81%  (2688/3307)84%  (542,1/643)
getMoney (int, int): long 100% (1/1)17%  (21/121)26%  (5,8/22)
getBytes (int, int): byte [] 100% (1/1)30%  (29/97)33%  (8/24)
getDouble (int, int): double 100% (1/1)56%  (65/117)60%  (15/25)
getFloat (int, int): float 100% (1/1)56%  (65/117)60%  (15/25)
getNumeric (int, int): MutableNumeric 100% (1/1)60%  (81/136)68%  (15/22)
getBoolean (int, int): boolean 100% (1/1)60%  (105/175)70%  (18,2/26)
getInt (int, int): int 100% (1/1)65%  (74/114)68%  (17/25)
getLong (int, int): long 100% (1/1)68%  (77/113)76%  (19/25)
readPageHeader (): void 100% (1/1)71%  (25/35)88%  (7/8)
readColumn (Table, int): Column 100% (1/1)77%  (51/66)79%  (11/14)
writeBinary (byte [], int, boolean): void 100% (1/1)80%  (72/90)91%  (11,8/13)
writeExpression (Expression, Column): void 100% (1/1)83%  (213/256)92%  (71/77)
createWriteLock (): void 100% (1/1)85%  (17/20)80%  (4/5)
writeFinsh (SSConnection): long 100% (1/1)85%  (64/75)95%  (19/20)
readLongString (): String 100% (1/1)88%  (23/26)96%  (3,8/4)
writeByte (int): void 100% (1/1)88%  (23/26)94%  (3,8/4)
writeBoolean (boolean): void 100% (1/1)90%  (27/30)94%  (3,8/4)
createStore (Table, StorePage, int, long): StoreImpl 100% (1/1)91%  (87/96)95%  (23,6/25)
writeString (String, int, boolean): void 100% (1/1)91%  (63/69)91%  (11,8/13)
writeShort (int): void 100% (1/1)92%  (37/40)95%  (4,8/5)
scanObjectOffsets (int [], int []): void 100% (1/1)93%  (105/113)96%  (26/27)
writeInt (int): void 100% (1/1)96%  (65/68)97%  (6,8/7)
getObject (int, int): Object 100% (1/1)97%  (118/122)96%  (25/26)
getString (int, int): String 100% (1/1)97%  (126/130)96%  (26/27)
<static initializer> 100% (1/1)100% (4/4)100% (2/2)
StoreImpl (Table, StorePage, int, long): void 100% (1/1)100% (15/15)100% (6/6)
copyValueFrom (StoreImpl, int, int): void 100% (1/1)100% (16/16)100% (3/3)
deleteRow (SSConnection): void 100% (1/1)100% (13/13)100% (5/5)
getCurrentOffsetInPage (): int 100% (1/1)100% (3/3)100% (1/1)
getLink (): StorePageLink 100% (1/1)100% (5/5)100% (1/1)
getNextPagePos (): long 100% (1/1)100% (21/21)100% (4/4)
getUsedSize (): int 100% (1/1)100% (3/3)100% (1/1)
isNull (int): boolean 100% (1/1)100% (9/9)100% (1/1)
isValidPage (): boolean 100% (1/1)100% (14/14)100% (1/1)
loadUpdatedStore (): StoreImpl 100% (1/1)100% (23/23)100% (4/4)
readBinary (): byte [] 100% (1/1)100% (7/7)100% (2/2)
readBoolean (): boolean 100% (1/1)100% (15/15)100% (1/1)
readByte (): int 100% (1/1)100% (11/11)100% (1/1)
readBytes (int): byte [] 100% (1/1)100% (19/19)100% (4/4)
readChars (int): char [] 100% (1/1)100% (41/41)100% (4/4)
readDate (): long 100% (1/1)100% (6/6)100% (1/1)
readDouble (): double 100% (1/1)100% (4/4)100% (1/1)
readFloat (): float 100% (1/1)100% (4/4)100% (1/1)
readInt (): int 100% (1/1)100% (56/56)100% (4/4)
readLong (): long 100% (1/1)100% (124/124)100% (8/8)
readLongBinary (): byte [] 100% (1/1)100% (18/18)100% (3/3)
readNumeric (): MutableNumeric 100% (1/1)100% (30/30)100% (6/6)
readShort (): int 100% (1/1)100% (26/26)100% (1/1)
readSmallDateTime (): long 100% (1/1)100% (6/6)100% (1/1)
readString (): String 100% (1/1)100% (10/10)100% (2/2)
readTime (): long 100% (1/1)100% (6/6)100% (1/1)
readTimestamp (): long 100% (1/1)100% (3/3)100% (1/1)
readUnsignedByte (): int 100% (1/1)100% (13/13)100% (1/1)
recreateStore (Table, StorePage, int): StoreImpl 100% (1/1)100% (22/22)100% (6/6)
resizePage (int): void 100% (1/1)100% (24/24)100% (5/5)
setCurrentOffsetInPage (int): void 100% (1/1)100% (4/4)100% (2/2)
updateFinsh (SSConnection, StoreImpl): void 100% (1/1)100% (92/92)100% (21/21)
writeBytes (byte []): void 100% (1/1)100% (17/17)100% (3/3)
writeChars (char []): void 100% (1/1)100% (41/41)100% (6/6)
writeColumn (Table, Column): void 100% (1/1)100% (67/67)100% (13/13)
writeDate (long): void 100% (1/1)100% (7/7)100% (2/2)
writeDouble (double): void 100% (1/1)100% (5/5)100% (2/2)
writeFloat (float): void 100% (1/1)100% (5/5)100% (2/2)
writeLong (long): void 100% (1/1)100% (132/132)100% (11/11)
writeLongBinary (byte []): void 100% (1/1)100% (27/27)100% (5/5)
writeLongString (String): void 100% (1/1)100% (32/32)100% (6/6)
writeNumeric (MutableNumeric): void 100% (1/1)100% (29/29)100% (6/6)
writeSmallDateTime (long): void 100% (1/1)100% (7/7)100% (2/2)
writeString (String): void 100% (1/1)100% (6/6)100% (2/2)
writeTime (long): void 100% (1/1)100% (9/9)100% (2/2)
writeTimestamp (long): void 100% (1/1)100% (4/4)100% (2/2)

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 */
33package smallsql.database;
34 
35import java.io.*;
36import java.sql.SQLException;
37 
38 
39public 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{
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();
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{
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{
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{
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{
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(""+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{
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{
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 = Table.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 = Table.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 
277Write 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.value.length );
392        writeByte( num.scale );
393        writeByte( num.signum );
394        for(int i=0; i<num.value.length; i++){
395            writeInt( num.value[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 strDaten ) throws SQLException{
442        writeString( strDaten, Short.MAX_VALUE, true );
443    }
444 
445    void writeString( String strDaten, int lengthColumn, boolean varchar ) throws SQLException{
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 readString(){
465        int length = readShort();
466        return new String( 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{
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{
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{
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 daten) throws Exception{
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 readLongString() throws Exception{
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(store.readChars( store.readInt() ) );
549    }
550        
551 
552    void writeColumn( Table table, Column column ) throws Exception{
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 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{
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 def = readString();
591                        column.setDefaultValue( new SQLParser().parseExpression(def), def);
592                }
593        return column;
594    }
595 
596    
597    void copyValueFrom( StoreImpl store, int offset, int length){
598                System.arraycopy( store.page, offset, 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{
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();
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(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{
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().signum != 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{
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{
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{
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{
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{
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();
1118        }
1119    }
1120 
1121    // wird für ResultSet.getBigDecimal() verwendet
1122    MutableNumeric getNumeric( int offset, int dataType) throws Exception{
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();
1175        }
1176    }
1177 
1178 
1179 
1180    // wird für ResultSet.getObject() verwendet
1181    Object getObject( int offset, int dataType) throws Exception{
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(readLong());
1199            case SQLTokenizer.REAL:
1200                    return new Float( readFloat() );
1201            case SQLTokenizer.FLOAT:
1202            case SQLTokenizer.DOUBLE:
1203                    return new Double( 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();
1239        }
1240    }
1241 
1242    // wird für ResultSet.getString() verwendet
1243    String getString( int offset, int dataType) throws Exception{
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();
1302        }
1303    }
1304 
1305    // wird für ResultSet.getBytes() verwendet
1306    byte[] getBytes( int offset, int dataType) throws Exception{
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();
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(String.valueOf( dataTypes[i] ) );
1423            }
1424        }
1425    }
1426 
1427        void deleteRow(SSConnection con) throws SQLException{
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}

[all classes][smallsql.database]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov