📄 table.java
字号:
/* =============================================================
* SmallSQL : a free Java DBMS library for the Java(tm) platform
* =============================================================
*
* (C) Copyright 2004-2006, by Volker Berlin.
*
* Project Info: http://www.smallsql.de/
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ---------------
* Table.java
* ---------------
* Author: Volker Berlin
*
*/
package smallsql.database;
import java.io.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
class Table extends TableView{
private static final int INDEX = 1;
final Database database;
RandomAccessFile raFile; // file handle of the table
private Lobs lobs; // file handle of lob data for this table
long firstPage; // offset of the first page
final private HashMap locks = new HashMap();
private SSConnection tabLockConnection; // wenn gesetzt die Connection die ein LOCK_TAB hat
private int tabLockCount;
final private ArrayList locksInsert = new ArrayList(); // liste der LOCK_INSERT
final private HashMap serializeConnections = new HashMap();
final IndexDescriptions indexes;
final ForeignKeys references;
/**
* Constructor for read existing tables.
*/
Table( Database database, SSConnection con, String name, RandomAccessFile raFile, long offset, int tableFormatVersion) throws Exception{
super( name, new Columns() );
this.database = database;
this.raFile = raFile;
this.firstPage = offset;
StoreImpl store = getStore(con, firstPage, SQLTokenizer.SELECT);
if(store == null){
throw Utils.createSQLException("File '" + getFile(database) + "' does not include a valid SmallSQL Table.");
}
int count = store.readInt();
for(int i=0; i<count; i++){
columns.add( store.readColumn(this, tableFormatVersion) );
}
indexes = new IndexDescriptions();
references = new ForeignKeys();
// read additional informations
int type;
while((type = store.readInt()) != 0){
int offsetInPage = store.getCurrentOffsetInPage();
int size = store.readInt();
switch(type){
case INDEX:
indexes.add( IndexDescription.load( database, this, store) );
break;
}
store.setCurrentOffsetInPage(offsetInPage + size);
}
firstPage = store.getNextPagePos();
}
/**
* Constructor for creating of new tables.
*/
Table(Database database, SSConnection con, String name, Columns columns, IndexDescriptions indexes, ForeignKeys foreignKeys) throws Exception{
this(database, con, name, columns, null, indexes, foreignKeys);
}
/**
* Constructor for alter an existing tables.
*/
Table(Database database, SSConnection con, String name, Columns columns, IndexDescriptions existIndexes, IndexDescriptions newIndexes, ForeignKeys foreignKeys) throws Exception{
super( name, columns );
this.database = database;
this.references = foreignKeys;
newIndexes.create( database, this );
if(existIndexes == null){
this.indexes = newIndexes;
}else{
this.indexes = existIndexes;
existIndexes.add(newIndexes);
}
write(con);
for(int i=0; i<foreignKeys.size(); i++){
ForeignKey foreignKey = foreignKeys.get(i);
Table pkTable = (Table)database.getTableView(con, foreignKey.pkTable);
pkTable.references.add(foreignKey);
}
}
/**
* Constructor for extends class Lobs.
*/
Table(Database database, String name){
super( name, null);
this.database = database;
indexes = null;
references = null;
}
/**
* Drop the Table. This method is static that the file does not need to load and also corrupt files can be dropped.
*/
static void drop(Database database, String name) throws Exception{
boolean ok = new File( Utils.createTableViewFileName( database, name ) ).delete();
if(!ok) throw Utils.createSQLException("Table '" + name + "' can't drop.");
}
/**
* Drop a loaded table.
*
*/
void drop(SSConnection con) throws Exception{
TableStorePage storePage = requestLock( con, SQLTokenizer.CREATE, -1 );
if(storePage == null){
throw Utils.createSQLException("Table '" + name + "' can't drop because is locked.");
}
// remove the all commits that point to this table
con.rollbackFile(raFile);
close();
if(lobs != null)
lobs.drop(con);
if(indexes != null)
indexes.drop(database);
boolean ok = getFile(database).delete();
if(!ok) throw Utils.createSQLException("Table '" + name + "' can't drop.");
}
/**
* Closed the file handle that the object can be garbaged.
*/
void close() throws Exception{
if(indexes != null)
indexes.close();
raFile.close();
raFile = null;
}
private void write(SSConnection con) throws Exception{
raFile = createFile( database );
firstPage = 8;
StoreImpl store = getStore( con, firstPage, SQLTokenizer.CREATE);
int count = columns.size();
store.writeInt( count );
for(int i=0; i<count; i++){
store.writeColumn( this, columns.get(i) );
}
// write additional informations
for(int i=0; i<indexes.size(); i++){
IndexDescription indexDesc = indexes.get(i);
store.writeInt( INDEX );
int offsetStart = store.getCurrentOffsetInPage();
store.setCurrentOffsetInPage( offsetStart + 4 ); // place holder for length
// write the IndexDescription
indexDesc.save(store);
// write the length information
int offsetEnd = store.getCurrentOffsetInPage();
store.setCurrentOffsetInPage( offsetStart );
store.writeInt( offsetEnd - offsetStart);
store.setCurrentOffsetInPage( offsetEnd );
}
store.writeInt( 0 ); // no more additional informations
store.writeFinsh(null); //The connection parameter is null because the table header is written immediately.
firstPage = store.getNextPagePos();
}
void writeMagic(RandomAccessFile raFile) throws Exception{
raFile.writeInt(MAGIC_TABLE);
raFile.writeInt(TABLE_VIEW_VERSION);
}
/*StoreImpl getStoreCreate( SSConnection con, long filePos ) throws Exception{
return StoreImpl.createStore( con, raFile, SQLTokenizer.CREATE, filePos );
}*/
StoreImpl getStore( SSConnection con, long filePos, int pageOperation ) throws Exception{
TableStorePage storePage = requestLock( con, pageOperation, filePos );
return StoreImpl.createStore( this, storePage, pageOperation, filePos );
}
StoreImpl getStore( TableStorePage storePage, int pageOperation ) throws Exception{
// is used for not commited INSERT pages, a new lock is not needed
return StoreImpl.recreateStore( this, storePage, pageOperation );
}
/*StoreImpl getStoreUpdate( SSConnection con, long filePos ) throws Exception{
return StoreImpl.createStore( con, raFile, SQLTokenizer.UPDATE, filePos );
}
StoreImpl getStoreDelete( SSConnection con, long filePos ) throws Exception{
return StoreImpl.createStore( con, raFile, SQLTokenizer.DELETE, filePos );
}*/
StoreImpl getStoreInsert( SSConnection con ) throws Exception{
TableStorePage storePage = requestLock( con, SQLTokenizer.INSERT, -1 );
return StoreImpl.createStore( this, storePage, SQLTokenizer.INSERT, -1 );
}
/**
* Create a Store that is not invoke in a transaction for copy of data.
*/
StoreImpl getStoreTemp( SSConnection con ) throws Exception{
TableStorePage storePage = new TableStorePage( con, this, LOCK_NONE, -2);
return StoreImpl.createStore( this, storePage, SQLTokenizer.INSERT, -2 );
}
StoreImpl getLobStore(SSConnection con, long filePos, int pageOperation) throws Exception{
if(lobs == null){
lobs = new Lobs( this );
}
return lobs.getStore( con, filePos, pageOperation );
}
/**
* Return the file offset of the first page with data after the table declaration.
* This is equals to the first row.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -