Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.scudata.dw.PhyTable Maven / Gradle / Ivy
Go to download
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.dw;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.FileObject;
import com.scudata.dm.LongArray;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.cursor.ConjxCursor;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MergeCursor2;
import com.scudata.dm.cursor.MultipathCursors;
import com.scudata.dm.op.Select;
import com.scudata.expression.CurrentElement;
import com.scudata.expression.Expression;
import com.scudata.expression.FieldRef;
import com.scudata.expression.IParam;
import com.scudata.expression.Node;
import com.scudata.expression.Operator;
import com.scudata.expression.UnknownSymbol;
import com.scudata.expression.ValueList;
import com.scudata.expression.fn.string.Like;
import com.scudata.expression.mfn.sequence.Contain;
import com.scudata.expression.mfn.serial.Sbs;
import com.scudata.expression.operator.Add;
import com.scudata.expression.operator.And;
import com.scudata.expression.operator.DotOperator;
import com.scudata.expression.operator.Equals;
import com.scudata.expression.operator.Greater;
import com.scudata.expression.operator.NotGreater;
import com.scudata.expression.operator.NotSmaller;
import com.scudata.expression.operator.Smaller;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;
/**
* ?ֶ?Ԫ????
* ע?⣺blob?ֶλ??ַ????ֶ?????????ڴ????
* @author runqian
*
*/
abstract public class PhyTable implements IPhyTable {
protected static String KEY_PREFIX = "#"; // ?????ֶ?ǰ
protected static int MIN_BLOCK_RECORD_COUNT = 8192; // ÿ?????С??¼???????ֵͬ?IJ?????ϲ?????
protected static int MAX_BLOCK_RECORD_COUNT = 8192 * 20; // ÿ???????¼???????ֵͬ?ij??????ɶ??
protected byte []reserve = new byte[32]; // ????λ???ֽ?1??Ű汾??
protected ComTable groupTable;
protected PhyTable parent;
protected ArrayList tableList; // ?????б?
protected String segmentCol; // ?ֶ???
protected int segmentSerialLen;
protected String tableName;
protected String []colNames; // ??#??ͷ??ʾά???????а?#ȥ??
protected String []allColNames;//????????????
protected int dataBlockCount;
protected long totalRecordCount;
protected BlockLink segmentBlockLink; // ?ֶ???Ϣ???????????μ?¼ÿ???п?ļ?¼??
protected byte curModifyBlock;//???? ??ǰ
protected BlockLink modifyBlockLink1; // ???? 1
protected BlockLink modifyBlockLink2; // ???? 2
protected Object []maxValues; // ????ӵļ?¼??ά?ֶ?ֵ??????ȷ???Ƿ??????Ψһ??????????????ж?
protected boolean hasPrimaryKey = true;// ?Ƿ??????????????ݵ?ʱ????Ҫ?ж?άֵ?Ƿ?Ψһ?????Ψһ???????
public boolean isSorted = true; // ?Ƿ??????ܲ?Ψһ??????
//index
protected String []indexNames;
protected String [][]indexFields;
protected String [][]indexValueFields;
//Ԥ????cuboid
protected String []cuboids;
protected transient DataStruct ds;
protected transient BlockLinkWriter segmentWriter;
protected transient ArrayList modifyRecords;
private transient HashMap> cache =
new HashMap>();
protected Sequence appendCache;//?ӻ???
//?ж??Ƿ??ǻ???
public boolean isBaseTable() {
return parent == null;
}
// ?ж?????Ƿ?ֻ??????һ????????û?и???
public boolean isSingleTable() {
return parent == null && (tableList == null || tableList.size() == 0);
}
public void close() {
getGroupTable().close();
}
public PhyTable createAnnexTable(String []colNames, int []serialBytesLen,
String tableName) throws IOException {
if (!hasPrimaryKey) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("dw.lessKey"));
}
if (getAnnexTable(tableName) != null) {
MessageManager mm = EngineMessage.get();
throw new RQException(tableName + mm.getMessage("dw.tableAlreadyExist"));
}
appendCache();
groupTable.checkWritable();
PhyTable table = null;
if (this instanceof ColPhyTable) {
table = new ColPhyTable(groupTable, colNames, serialBytesLen, tableName, (ColPhyTable)this);
} else {
table = new RowPhyTable(groupTable, colNames, serialBytesLen, tableName, (RowPhyTable)this);
}
tableList.add(table);
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.createAnnexTable(colNames, serialBytesLen, tableName);
}
groupTable.save();
return table;
}
public PhyTable getAnnexTable(String tableName) {
for (PhyTable table : tableList) {
if (table.isTable(tableName)) {
return table;
}
}
return null;
}
StructManager getStructManager() {
return groupTable.getStructManager();
}
public PhyTable getParent() {
return parent;
}
public ArrayList getTableList(){
return tableList;
}
public static void setMinBlockRecordCount(int count) {
MIN_BLOCK_RECORD_COUNT = count;
}
public static void setMaxBlockRecordCount(int count) {
MAX_BLOCK_RECORD_COUNT = count;
}
abstract protected void init();
public void setSegmentCol(String col, int serialLen) throws IOException {
if (col == null) return;
if (col.startsWith("#")) {
col = col.substring(1);
}
segmentCol = col;
segmentSerialLen = serialLen;
groupTable.save();
}
public String getSegmentCol() {
if (parent != null) {
return parent.getSegmentCol();
} else {
return segmentCol;
}
}
public int getSegmentSerialLen() {
if (parent != null) {
return parent.getSegmentSerialLen();
} else {
return segmentSerialLen;
}
}
public DataStruct getDataStruct() {
return ds;
}
public ComTable getGroupTable() {
return groupTable;
}
public String getTableName() {
return tableName;
}
/**
* ȡ?ֶ???????
* @return ?ֶ???????
*/
public String[] getColNames() {
return colNames;
}
/**
* ȡָ???ֶε??ֶ???
* @param col
* @return
*/
public String getColName(int col) {
return colNames[col];
}
public String[] getAllColNames() {
if (parent == null) return colNames;
return allColNames;
}
public String[] getIndexNames() {
return indexNames;
}
public String[][] getIndexFields() {
return indexFields;
}
public String[][] getIndexValueFields() {
return indexValueFields;
}
/**
* ????Ҫ???????ֶ?ѡ??һ?????ʵ??????????֣?û?к??ʵ??ؿ?
* @param fieldNames
* @return
*/
public String chooseIndex(String[] fieldNames) {
if (fieldNames == null || indexNames == null)
return null;
ArrayList list = new ArrayList();
int count = indexNames.length;
int fcount = fieldNames.length;
for (int i = 0; i < count; i++) {
int cnt = indexFields[i].length;
if (cnt < fcount)
continue;
list.clear();
for (int j = 0; j < fcount; j++) {
list.add(indexFields[i][j]);
}
for (String str : fieldNames) {
list.remove(str);
}
if (list.isEmpty()) {
return indexNames[i];
}
}
return null;
}
/**
* ɾ??????,???indexNameΪnull????ʾɾ??????
*/
public boolean deleteIndex(String indexName) throws IOException {
getGroupTable().checkWritable();
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.deleteIndex(indexName);
}
String[] oldFileName = indexNames;
FileObject tmpFile;
String dir = groupTable.getFile().getAbsolutePath() + "_";
if (oldFileName == null)
return false;
if (indexName == null) {
for (String name : oldFileName) {
tmpFile = new FileObject(dir + tableName + "_" + name);
tmpFile.delete();
}
indexNames = null;
} else {
tmpFile = new FileObject(dir + tableName + "_" + indexName);
if (!tmpFile.isExists())
return false;
int size = oldFileName.length;
int id = -1;
for (int i = 0; i < size; i++) {
if (oldFileName[i].equals(indexName)) {
id = i;
break;
}
}
if (id < 0)
return false;
if (size == 1) {
this.indexNames = null;
this.indexFields = null;
this.indexValueFields = null;
} else {
String[][] oldIndexFields = this.indexFields;
String[][] oldIndexValueFields = this.indexValueFields;
this.indexNames = new String[size - 1];
this.indexFields = new String[size - 1][];
this.indexValueFields = new String[size - 1][];
int j = 0;
for (int i = 0; i < size; i++) {
if (i == id)
continue;
this.indexNames[j] = oldFileName[i];
this.indexFields[j] = oldIndexFields[i];
this.indexValueFields[j] = oldIndexValueFields[i];
j++;
}
}
tmpFile.delete();
}
groupTable.save();
return true;
}
/**
* ????һ??????
* @param indexName ????????
* @param indexFields ?????ֶ?
* @param indexValueFields ֵ?ֶΣ?KV???????У?
* @throws IOException
*/
public void addIndex(String indexName, String[] indexFields, String[] indexValueFields) throws IOException {
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.addIndex(indexName, indexFields, indexValueFields);
}
int size = 0;
if (indexNames != null) {
size = indexNames.length;
}
String[] newNames = new String[size + 1];
String[][] newFieldNames = new String[size + 1][];
String[][] newValueFieldNames = new String[size + 1][];
if (size > 0) {
System.arraycopy(indexNames, 0, newNames, 0, size);
System.arraycopy(this.indexFields, 0, newFieldNames, 0, size);
System.arraycopy(this.indexValueFields, 0, newValueFieldNames, 0, size);
}
newNames[size] = indexName;
newFieldNames[size] = indexFields;
newValueFieldNames[size] = indexValueFields;
indexNames = newNames;
this.indexFields = newFieldNames;
this.indexValueFields = newValueFieldNames;
groupTable.save();
}
/**
* ????????
*/
public void updateIndex() {
if (indexNames == null) {
return;
}
Context ctx = groupTable.ctx;
byte type[];
FileObject tmpFile;
String dir = groupTable.getFile().getAbsolutePath() + "_";
int size = indexNames.length;
for (int i = 0; i < size; i++) {
tmpFile = new FileObject(dir + tableName + "_" + indexNames[i]);
try {
type = (byte[]) tmpFile.read(6, 6, "b");
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
//????iname?õ??????ֶ?
String []ifields = indexFields[i];
String []vfields = indexValueFields[i];
if (type[0] == 'h') {
TableHashIndex index = new TableHashIndex(this, indexNames[i]);
index.setFields(ifields, vfields);
index.create(indexFields[i], "a", ctx, null);
} else if (type[0] == 'x') {
PhyTableIndex index = new PhyTableIndex(this, indexNames[i]);
index.setFields(ifields, vfields);
index.create(indexFields[i], "a", ctx, null);
} else {
TableKeyValueIndex index = new TableKeyValueIndex(this, indexNames[i]);
index.setFields(ifields, vfields);
index.create(indexFields[i], indexValueFields[i], "a", ctx, null);
}
}
}
public void createIndex(String I, String []fields, Object obj, String opt, Expression w, Context ctx) {
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.createIndex(I, fields, obj, opt, w, ctx);
}
try {
appendCache();
} catch (IOException e) {
throw new RQException(e);
}
if (obj == null) {
if (opt != null) {
//ȫ??
if (opt.indexOf('w') != -1) {
TableFulltextIndex index = new TableFulltextIndex(this, I, (Integer) obj);
index.create(fields, opt, ctx, w);
return;
}
//load index
FileObject indexFile = null;
String dir = getGroupTable().getFile().getAbsolutePath() + "_";
if (I != null) {
indexFile = new FileObject(dir + getTableName() + "_" + I);
if (!indexFile.isExists()) {
return;
}
}
ITableIndex index = getTableMetaDataIndex(indexFile, I, true);
if (opt.indexOf('2') != -1) {
index.loadAllBlockInfo();
} else if (opt.indexOf('3') != -1) {
index.loadAllKeys();
} else if (opt.indexOf('0') != -1) {
index.unloadAllBlockInfo();
}
return;
}
//????
PhyTableIndex index = new PhyTableIndex(this, I);
index.create(fields, opt, ctx, w);
} else if (obj instanceof String[]) {
//KV
TableKeyValueIndex index = new TableKeyValueIndex(this, I);
index.create(fields, (String[]) obj, opt, ctx, w);
} else if (obj instanceof Integer) {
//hash
TableHashIndex index = new TableHashIndex(this, I, (Integer) obj);
index.create(fields, opt, ctx, w);
}
}
public void createIndex(FileObject file, String []fields, Object obj, String opt, Expression w, Context ctx) {
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.createIndex(file, fields, obj, opt, w, ctx);
}
try {
appendCache();
} catch (IOException e) {
throw new RQException(e);
}
boolean hasOpt = false;
//???浽?????
if (opt == null) {
opt = "U";
} else {
hasOpt = true;
opt += "U";
}
if (hasOpt) {
//ȫ??
if (opt.indexOf('w') != -1) {
TableFulltextIndex index = new TableFulltextIndex(this, file, (Integer) obj);
index.create(fields, opt, ctx, w);
return;
}
}
if (obj == null) {
if (hasOpt) {
//load index
FileObject indexFile = file;
String[][] fileds = PhyTableIndex.readIndexFields(file);
ITableIndex index = getTableMetaDataIndex(indexFile, fileds[0], fileds[1], true);
if (opt.indexOf('2') != -1) {
index.loadAllBlockInfo();
} else if (opt.indexOf('3') != -1) {
index.loadAllKeys();
} else if (opt.indexOf('0') != -1) {
index.unloadAllBlockInfo();
}
return;
}
//????
PhyTableIndex index = new PhyTableIndex(this, file);
index.create(fields, opt, ctx, w);
} else if (obj instanceof String[]) {
//KV
TableKeyValueIndex index = new TableKeyValueIndex(this, file);
index.create(fields, (String[]) obj, opt, ctx, w);
} else if (obj instanceof Integer) {
//hash
TableHashIndex index = new TableHashIndex(this, file, (Integer) obj);
index.create(fields, opt, ctx, w);
}
}
/**
* ?ؽ?????
* @param ctx
*/
public void resetIndex(Context ctx) {
getGroupTable().checkWritable();
if (indexNames == null) {
return;
}
byte type[];
FileObject tmpFile;
String dir = groupTable.getFile().getAbsolutePath() + "_";
int size = indexNames.length;
for (int i = 0; i < size; i++) {
tmpFile = new FileObject(dir + tableName + "_" + indexNames[i]);
try {
type = (byte[]) tmpFile.read(6, 6, "b");
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
if (type[0] == 'h') {
TableHashIndex index = new TableHashIndex(this, indexNames[i]);
index.create(indexFields[i], "ar", ctx, null);
} else if (type[0] == 'x') {
PhyTableIndex index = new PhyTableIndex(this, indexNames[i]);
index.create(indexFields[i], "ar", ctx, null);
} else if (type[0] == 'v') {
TableKeyValueIndex index = new TableKeyValueIndex(this, indexNames[i]);
index.create(indexFields[i], indexValueFields[i], "ar", ctx, null);
} else {
TableFulltextIndex index = new TableFulltextIndex(this, indexNames[i], null);
index.create(indexFields[i], "ar", ctx, null);
}
}
}
abstract public String[] getSortedColNames();
abstract public String[] getAllSortedColNames();
/**
* ?õ?ά?е?λ??
* @return
*/
public int[] getSortedColIndex() {
String []keyNames;
if (parent == null) {
keyNames = getSortedColNames();
} else {
keyNames = getAllSortedColNames();
}
int sortedColCount = keyNames.length;
int []findex = new int[sortedColCount];
for (int f = 0; f < sortedColCount; ++f) {
findex[f] = ds.getFieldIndex(keyNames[f]);
}
return findex;
}
public boolean isTable(String name) {
return tableName.equals(name);
}
//??¼???????????????ļ?¼??
public long getTotalRecordCount() {
return totalRecordCount;
}
/**
* ȡʵ???ܼ?¼?????????˲????ļ?¼??
* @return
*/
public long getActualRecordCount() {
long count = this.totalRecordCount;
ArrayList modifyRecords = getModifyRecords();
if (modifyRecords != null) {
for (ModifyRecord r : modifyRecords) {
if (r.isDelete()) {
count--;
} else if (r.isInsert()) {
count++;
}
}
}
return count;
}
/**
* ?ܿ???
* @return
*/
public int getDataBlockCount() {
return dataBlockCount;
}
/**
* ά?ֶεĸ???
* @return
*/
public int getAllSortedColNamesLength() {
String []names = getAllSortedColNames();
if (names == null) {
return 0;
} else {
return names.length;
}
}
/**
* ?Ƿ???????
* @return
*/
public boolean hasPrimaryKey() {
return hasPrimaryKey;
}
abstract protected void applyFirstBlock() throws IOException;
public BlockLinkReader getSegmentReader() {
BlockLinkReader reader = new BlockLinkReader(segmentBlockLink);
try {
reader.loadFirstBlock();
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
return reader;
}
// ??д???ӡ?ɾ??????????ǰ????
abstract protected void prepareAppend() throws IOException;
// ????д
abstract protected void finishAppend() throws IOException;
public abstract void readExternal(BufferReader reader) throws IOException;
public abstract void writeExternal(BufferWriter writer) throws IOException;
//д?뻺???????
public abstract void appendCache() throws IOException;
public abstract int[] getSerialBytesLen();
/**
* д????
* @throws IOException
*/
protected void saveModifyRecords() throws IOException {
BufferWriter writer = new BufferWriter(getStructManager());
ArrayList modifyRecords = this.modifyRecords;
if (modifyRecords == null) return;
int count = modifyRecords.size();
writer.writeInt(count);
for (int i = 0; i < count; ++i) {
ModifyRecord r = modifyRecords.get(i);
r.writeExternal(writer);
}
// ??д????ʱ??ͬ????֧??ͬʱ??д
Object syncObj = groupTable.getSyncObject();
synchronized(syncObj) {
BlockLink modifyBlockLink = null;
if (curModifyBlock == 2) {
modifyBlockLink = modifyBlockLink1;
curModifyBlock = 1;
} else {
modifyBlockLink = modifyBlockLink2;
curModifyBlock = 2;
}
if (modifyBlockLink.isEmpty()) {
modifyBlockLink.setFirstBlockPos(groupTable.applyNewBlock());
}
BlockLinkWriter blockWriter = new BlockLinkWriter(modifyBlockLink, false);
blockWriter.rewriteBlocks(writer.finish());
blockWriter.close();
}
}
/**
* ??????
* @return
*/
public ArrayList getModifyRecords() {
if (modifyRecords != null) {
if (modifyRecords.size() == 0) {
return null;
}
return modifyRecords;
}
if (modifyBlockLink1.isEmpty() && modifyBlockLink2.isEmpty()) {
return null;
}
try {
// ??д????ʱ??ͬ????֧??ͬʱ??д
byte []bytes;
Object syncObj = groupTable.getSyncObject();
synchronized(syncObj) {
BlockLink modifyBlockLink = null;
if (curModifyBlock == 2) {
modifyBlockLink = modifyBlockLink2;
} else {
modifyBlockLink = modifyBlockLink1;
}
BlockLinkReader blockReader = new BlockLinkReader(modifyBlockLink);
bytes = blockReader.readBlocks();
blockReader.close();
}
BufferReader reader = new BufferReader(getStructManager(), bytes);
int count = reader.readInt();
ArrayList modifyRecords = new ArrayList(count);
this.modifyRecords = modifyRecords;
DataStruct ds = new DataStruct(getAllColNames());
for (int i = 0; i < count; ++i) {
ModifyRecord r = new ModifyRecord();
r.readExternal(reader, ds);
modifyRecords.add(r);
}
if (count == 0) {
return null;
}
return modifyRecords;
} catch (IOException e) {
throw new RQException(e);
}
}
abstract public Sequence update(Sequence data, String opt) throws IOException;
abstract public Sequence delete(Sequence data, String opt) throws IOException;
/**
* ??ñ???ʽexp???漰???????ֶ?
* @param exp
* @param colNames
* @return
*/
public static String[] getExpFields(Expression exp, String[] colNames) {
ArrayList fields = new ArrayList();
getExpIndex(exp.getHome(), fields, colNames);
int size = fields.size();
if (size == 0) {
return null;
} else {
String[] array = new String[size];
fields.toArray(array);
return array;
}
}
/**
* ??ȡexp????Ҫ??????ֶ?(k.sbs() k1+k2)
* @param exps
* @return
*/
public ArrayList getExpFields(Expression []exps) {
if (exps == null) {
return null;
}
ArrayList result = new ArrayList();
String []columns = getAllColNames();
int srcCount = columns.length;
int count = exps.length;
Next:
for (int i = 0; i < count; ++i) {
if (exps[i].getHome() instanceof DotOperator) {
String col = null;
Node left = exps[i].getHome().getLeft();
Node right = exps[i].getHome().getRight();
if (left instanceof UnknownSymbol && right instanceof Sbs) {
col = ((UnknownSymbol)left).getName();
} else {
continue;
}
for (int s = 0; s < srcCount; ++s) {
if (columns[s].equals(col)) {
if (! result.contains(columns[s])) {
result.add(columns[s]);
}
continue Next;
}
}
MessageManager mm = EngineMessage.get();
throw new RQException(col + mm.getMessage("ds.fieldNotExist"));
}
if (exps[i].getHome() instanceof Add) {
String col1 = null;
String col2 = null;
Object obj1 = exps[i].getHome().getLeft();
Object obj2 = exps[i].getHome().getRight();
if ((obj1 instanceof UnknownSymbol)
&& (obj2 instanceof UnknownSymbol)) {
col1 = ((UnknownSymbol)obj1).getName();
col2 = ((UnknownSymbol)obj2).getName();
}
boolean b1 = false,b2 = false;
for (int s = 0; s < srcCount; ++s) {
if (columns[s].equals(col1)) {
if (! result.contains(columns[s])) {
result.add(columns[s]);
}
b1 = true;
}
if (columns[s].equals(col2)) {
if (! result.contains(columns[s])) {
result.add(columns[s]);
}
b2 = true;
}
}
if (b1 && b2) continue;
MessageManager mm = EngineMessage.get();
throw new RQException(col1 + " or " + col2 + mm.getMessage("ds.fieldNotExist"));
}
}
if (result.size() == 0) {
return null;
}
return result;
}
private static void getExpIndex(Node home, ArrayList fields, String[] colNames) {
int index = getKeyIndex(home, colNames);
if (index >= 0) {
String s = colNames[index];
if (!fields.contains(s)) {
fields.add(s);
}
return;
}
Node left = home.getLeft();
Node right = home.getRight();
if (left != null)
getExpIndex(left, fields, colNames);
if (right != null)
getExpIndex(right, fields, colNames);
}
/**
* ???node???ֶ???keyNames?е?index
* @param node
* @param keyNames
* @return
*/
private static int getKeyIndex(Node node, String[] keyNames) {
if (node instanceof UnknownSymbol) {
String keyName = ((UnknownSymbol) node).getName();
for (int i = 0, len = keyNames.length; i < len; ++i) {
if (keyName.equals(keyNames[i])) {
return i;
}
}
} else if (node instanceof DotOperator && node.getLeft() instanceof CurrentElement
&& node.getRight() instanceof FieldRef) { // ~.key
FieldRef fieldNode = (FieldRef) node.getRight();
String keyName = fieldNode.getName();
for (int i = 0, len = keyNames.length; i < len; ++i) {
if (keyName.equals(keyNames[i])) {
return i;
}
}
}
return -1;
}
/**
* ?Ӳ???ȡ??¼???ҹ???
* @param exp
* @param ctx
* @return
*/
public static ArrayList getModifyRecord(PhyTable table, Expression exp, Context ctx) {
ArrayList modifyRecords = table.getModifyRecords();
if (modifyRecords == null) return null;
int size = modifyRecords.size();
ArrayList mrs = new ArrayList(size);
for (int i = 0; i < size; i++) {
ModifyRecord mr = modifyRecords.get(i);
if (mr.isDelete()) {
mrs.add(mr);//delete?Ŀ϶?Ҫ
} else if (exp != null) {
Record sr = mr.getRecord();
if (Variant.isTrue(sr.calc(exp, ctx))) {
mrs.add(mr);//??????????update??insert??Ҫ
} else {
if (mr.isUpdate()) {
//????????????updateҪ???delete
ModifyRecord temp = new ModifyRecord(mr.getRecordSeq());
temp.setDelete();
mrs.add(temp);
}
}
} else {
mrs.add(mr);
}
}
if (mrs.size() == 0) {
return null;
} else {
return mrs;
}
}
/**
* ????Ƿ???ά?ֶΣ????????α??(??ַ)?ķ?Χ
* @param field
* @param node
* @param ctx
* @return
*/
abstract long[] checkDim(String field, Node node, Context ctx);
/**
* ??????ʽ?Ƿ???????????
* @param home ????ʽhome?ڵ?
* @param indexs ?????ÿ??????????????һ?????????һ?????????ҵ??????????ڶ????DZ???ʽ?ڵ?
* @param intervals ???????ʾ??ַ??Χ
* @param indexFiles ??ѡ???????ļ?
* @param ctx
*/
private void checkAnds(Node home, ArrayList indexs, ArrayList intervals, FileObject[] indexFiles, Context ctx) {
if (!(home instanceof Operator) &&
!(home instanceof Like)) {
return;
}
Node left = home.getLeft();
Node right = home.getRight();
if (home instanceof And) {
checkAnds(left, indexs, intervals, indexFiles, ctx);
checkAnds(right, indexs, intervals, indexFiles, ctx);
return;
} else {
String []fields = null;
if (home instanceof Equals ||
home instanceof NotSmaller ||
home instanceof Greater ||
home instanceof NotGreater ||
home instanceof Smaller ) {
if (left instanceof UnknownSymbol) {
fields = new String[1];
fields[0] = ((UnknownSymbol)left).getName();
} else if (right instanceof UnknownSymbol) {
fields = new String[1];
fields[0] = ((UnknownSymbol)right).getName();
}
} else if (home instanceof DotOperator) {
//contain
if (!(left instanceof ValueList) || !(right instanceof Contain)) {
return;
}
String str = ((Contain)right).getParamString();
str = str.replaceAll("\\[", "");
str = str.replaceAll("\\]", "");
str = str.replaceAll(" ", "");
fields = str.split(",");
} else if (home instanceof Like) {
if (((Like) home).getParam().getSubSize() != 2) {
return;
}
IParam sub1 = ((Like) home).getParam().getSub(0);
fields = new String[1];
fields[0] = (String) sub1.getLeafExpression().getIdentifierName();
}
if (fields == null) return;
ITableIndex index = null;
if (indexFiles == null) {
String indexName = chooseIndex(fields);
if (indexName == null) {
//????????????ֶΣ??????Ƿ???ά?ֶ?
long[] posArray = checkDim(fields[0], home, ctx);
if (posArray != null) {
for (long pos : posArray) {
if (!intervals.contains(pos)) {
intervals.add(pos);
}
}
}
return;
}
String dir = getGroupTable().getFile().getAbsolutePath() + "_";
FileObject indexFile = new FileObject(dir + getTableName() + "_" + indexName);
index = getTableMetaDataIndex(indexFile, indexName, true);
} else {
for (FileObject file : indexFiles) {
String[][] indexFileds = PhyTableIndex.readIndexFields(file);
if (PhyTableIndex.isCompatible(fields, indexFileds[0])) {
index = getTableMetaDataIndex(file, indexFileds[0], indexFileds[1], true);
break;
}
}
}
if (index == null) {
return;
}
if (index instanceof TableKeyValueIndex) {
//??F??????????
return;
}
if (index instanceof TableHashIndex) {
//hash????ֻ???Ż????ں?contain
if (!(home instanceof Equals) && !(home instanceof DotOperator)) {
return;
}
}
if (index instanceof TableFulltextIndex) {
//ȫ??????ֻ?ܴ???like *X* ģ????ѯ
IParam sub2 = ((Like) home).getParam().getSub(1);
String fmtExp = (String) sub2.getLeafExpression().calculate(null);
if (fmtExp.length() <= 2) {
return;
}
int idx = fmtExp.indexOf("*");
if (idx != 0) {
return;
}
fmtExp = fmtExp.substring(1);
idx = fmtExp.indexOf("*");
if (idx != fmtExp.length() - 1) {
return;
}
}
//?ϲ???ͬ??
if (home instanceof Equals ||
home instanceof NotSmaller ||
home instanceof Greater ||
home instanceof NotGreater ||
home instanceof Smaller ) {
int size = indexs.size();
for (int i = 0; i < size; i++) {
if (index == indexs.get(i)) {
Node node = (Node) indexs.get(i + 1);
And and = new And();
and.setLeft(node);
and.setRight(home);
indexs.set(i + 1, and);
return;
}
}
}
indexs.add(index);
indexs.add(home);
}
}
private LongArray longArrayUnite(LongArray a, ArrayList intervals) {
if (a == null || a.size() == 0) {
return a;
}
//ת??Ϊ???????????
int intervalSize = intervals.size();
Long[] intervalArray = new Long[intervalSize];
intervals.toArray(intervalArray);
Arrays.sort(intervalArray);
int j = 0;
int size = a.size();
LongArray c = new LongArray(size);
if (this instanceof RowPhyTable) {
for (int i = 0; i < size; i+=2) {
long seq = a.get(i);
long pos = a.get(i + 1);
while (j < intervalSize) {
long from = intervalArray[j];
long to = intervalArray[j + 1];
if (pos < from) {
break;
} else if (pos > to) {
j += 2;
} else if (pos >= from && pos <= to) {
c.add(seq);
c.add(pos);
break;
}
}
}
} else {
for (int i = 0; i < size; i++) {
long pos = a.get(i);
while (j < intervalSize) {
long from = intervalArray[j];
long to = intervalArray[j + 1];
if (pos < from) {
break;
} else if (pos > to) {
j += 2;
} else if (pos >= from && pos <= to) {
c.add(pos);
break;
}
}
}
}
return c;
}
static LongArray longArrayUnite(LongArray a, long []b) {
if (a == null) {
LongArray c = new LongArray(b.length);
for (long l : b) {
c.add(l);
}
return c;
}
int lenA = a.size();
int lenB = b.length;
if (lenB == 0) {
return a;
}
LongArray c = new LongArray(Math.min(lenA, lenB));
int i = 0, j = 0;
while (i < lenA && j < lenB) {
if (a.get(i) < b[j]) {
i++;
} else if (b[j] < a.get(i)) {
j++;
} else {
c.add(a.get(i));
i++;
j++;
}
}
return c;
}
static LongArray longArrayUnite(LongArray a, long []b, int posCount, boolean sort) {
int lenB = b.length;
posCount += 1;//????һ??α?ų???
if (sort) {
int size = lenB / posCount;
long [][]posArr = new long[size][];
for (int i = 0; i < size; i++) {
long[] posRecord = new long[posCount];
for (int c = 0; c < posCount; c++) {
posRecord[c] = b[i * posCount + c];
}
posArr[i] = posRecord;
}
Arrays.sort(posArr, new IndexCursor.PositionsComparator());
int i = 0;
for (long[] arr : posArr) {
for (long l : arr) {
b[i++] = l;
}
}
}
if (a == null) {
LongArray c = new LongArray(b.length);
for (long l : b) {
c.add(l);
}
return c;
}
int lenA = a.size();
if (lenB == 0) {
return a;
}
LongArray c = new LongArray(Math.min(lenA, lenB));
int i = 0, j = 0;
while (i < lenA && j < lenB) {
long longA = a.get(i + 1);
long longB = b[j + 1];
if (longA < longB) {
i += posCount;
} else if (longB < longA) {
j += posCount;
} else {
for (int k = 0; k < posCount; k++) {
c.add(a.get(i));
i++;
j++;
}
}
}
return c;
}
/**
* ?????Щα??ռ???˼???block
* @param recNums α??????
* @param recCountOfSegment ÿ??block??α??????
* @return
*/
public static int getBlockCount(LongArray recNums, long []recCountOfSegment) {
if (recNums == null || recNums.size() == 0) {
return 0;
}
int result = 0;
int size = recNums.size();
if (size == 1) {
return 1;
}
int len = recCountOfSegment.length;
int i = 0, j = 0;
boolean hasRec = false;
while (i < size && j < len) {
long recNum = recNums.get(i);
if (recNum <= recCountOfSegment[j]) {
if (!hasRec) {
result++;
hasRec = true;
}
i++;
continue;
} else {
j++;
hasRec = false;
}
}
return result;
}
/**
* ??????ѯ????icursor?????
*/
public ICursor icursor(String []fields, Expression filter, Object indexObj, String opt, Context ctx) {
ComTable groupTable = getGroupTable();
groupTable.checkReadable();
boolean isName = indexObj == null || indexObj instanceof String;
ICursor cs;
if (isName) {
cs = icursor_(fields, filter, (String) indexObj, opt, ctx);
} else {
cs = icursorByFile(fields, filter, (FileObject[]) indexObj, opt, ctx);
}
PhyTable tmd = getSupplementTable(false);
if (tmd == null) {
return cs;
} else {
ICursor cs2;
if (isName) {
cs2 = tmd.icursor_(fields, filter, (String) indexObj, opt, ctx);
} else {
cs2 = tmd.icursorByFile(fields, filter, (FileObject[]) indexObj, opt, ctx);
}
if (cs == null) {
return cs2;
}
if (cs2 == null) {
return cs;
}
int[] ifields = null;
if (cs instanceof IndexCursor) {
ifields = ((IndexCursor) cs).getSortFieldsIndex();
} else if (cs instanceof IndexFCursor) {
ifields = ((IndexFCursor) cs).getSortFieldsIndex();
}
if (ifields == null && cs2 != null) {
if (cs2 instanceof IndexCursor) {
ifields = ((IndexCursor) cs2).getSortFieldsIndex();
} else if (cs2 instanceof IndexFCursor) {
ifields = ((IndexFCursor) cs2).getSortFieldsIndex();
}
}
if (ifields != null && ifields.length > 0) {
return new MergeCursor2(cs, cs2, ifields, null, groupTable.ctx);
} else {
return new ConjxCursor(new ICursor[]{cs, cs2});
}
}
}
private ICursor icursor_(String []fields, Expression filter, String iname, String opt, Context ctx) {
FileObject indexFile = null;
//????Ƿ??????????AND?Ż?
if (filter.getHome() instanceof And) {
ArrayList indexs = new ArrayList();
ArrayList intervals = new ArrayList();
checkAnds(filter.getHome(), indexs, intervals, null, ctx);
int intervalSize = intervals.size();
if (intervalSize > 0 && intervalSize / 2 <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
//???ά???˵Ľ???????Ѿ???????
return cursor(fields, filter, ctx);
}
if (intervalSize == dataBlockCount * 2) {
//???ά???˵Ľ??ÿ?鶼??????,??û??????
intervals.clear();
intervalSize = 0;
}
int size = indexs.size();
if (size > 0) {
LongArray tempPos = null;
int i;
int maxRecordLen = 0;
Object []indexArray = new Object[size];
if (opt != null && opt.indexOf('u') != -1) {
//?????????ȼ?
indexs.toArray(indexArray);
} else {
//indexҪ???????ȼ?????
int j = 0;
i = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof Equals) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof Like) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof DotOperator) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if ((!(node instanceof Equals))
&&(!(node instanceof Like))
&&(!(node instanceof DotOperator))) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
}
i = 0;
boolean isRow = this instanceof RowPhyTable;
long recCountOfSegment[] = null;
if (!isRow) {
recCountOfSegment = ((ColPhyTable)this).getSegmentInfo();
}
while (i < size) {
ITableIndex index = (ITableIndex)indexArray[i++];
Node node = (Node) indexArray[i++];
LongArray srcPos = index.select(new Expression(node), opt, ctx);
int len = index.getMaxRecordLen();
if (len > 0) {
maxRecordLen = len;
}
boolean sort = true;
if (isRow) {
tempPos = longArrayUnite(tempPos, srcPos.toArray(), index.getPositionCount(), sort);
if (tempPos.size() <= ITableIndex.MIN_ICURSOR_REC_COUNT) {
break;
}
} else {
long [] arr = srcPos.toArray();
if (sort) {
Arrays.sort(arr);
}
tempPos = longArrayUnite(tempPos, arr);
if (getBlockCount(tempPos, recCountOfSegment) <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
break;
}
}
if (intervalSize > 0) {
//????ά???˵Ľ??
tempPos = longArrayUnite(tempPos, intervals);
intervalSize = 0;//ֻ????1??
if (isRow) {
if (tempPos.size() <= ITableIndex.MIN_ICURSOR_REC_COUNT) {
break;
}
} else {
if (getBlockCount(tempPos, recCountOfSegment) <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
break;
}
}
}
}
ArrayList mrl = getModifyRecord(this, filter, ctx);
if (tempPos != null && tempPos.size() > 0) {
ICursor cs = new IndexCursor(this, fields, null, tempPos.toArray(), opt, ctx);
if (cs instanceof IndexCursor) {
((IndexCursor) cs).setModifyRecordList(mrl);
if (maxRecordLen != 0) {
((IndexCursor) cs).setRowBufferSize(maxRecordLen);
}
}
Select select = new Select(filter, null);
cs.addOperation(select, ctx);
return cs;
} else {
if (mrl == null) {
return null;
} else {
return new IndexCursor(this, fields, null, null, opt, ctx);
}
}
}
}
String dir = getGroupTable().getFile().getAbsolutePath() + "_";
if (iname != null) {
indexFile = new FileObject(dir + getTableName() + "_" + iname);
if (!indexFile.isExists()) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("dw.indexNotExist") + " : " + iname);
}
} else {
String[] indexFields;
if (filter.getHome() instanceof DotOperator) {
Node right = filter.getHome().getRight();
if (!(right instanceof Contain)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
String str = ((Contain)right).getParamString();
str = str.replaceAll("\\[", "");
str = str.replaceAll("\\]", "");
str = str.replaceAll(" ", "");
indexFields = str.split(",");
} else if (filter.getHome() instanceof Like) {
IParam sub1 = ((Like) filter.getHome()).getParam().getSub(0);
String f = (String) sub1.getLeafExpression().getIdentifierName();
indexFields = new String[]{f};
} else {
indexFields = getExpFields(filter, getColNames());
}
String indexName = chooseIndex(indexFields);
if (indexFields == null || indexName == null) {
//filter?в??????κ??ֶ? or ??????????
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
indexFile = new FileObject(dir + getTableName() + "_" + indexName);
iname = indexName;
}
ITableIndex index = getTableMetaDataIndex(indexFile, iname, true);
ArrayList mrl = getModifyRecord(this, filter, ctx);
ICursor cursor = index.select(filter, fields, opt, ctx);
if (cursor == null) {
if (mrl == null) {
return null;
} else {
cursor = new IndexCursor(this, fields, null, null, opt, ctx);
}
} else {
if (cursor instanceof IndexCursor) {
((IndexCursor) cursor).setModifyRecordList(mrl);
}
}
return cursor;
}
private ICursor icursorByFile(String []fields, Expression filter, FileObject[] files, String opt, Context ctx) {
FileObject indexFile = null;
String[][] fileds = null;
//????Ƿ??????????AND?Ż?
if (filter.getHome() instanceof And) {
ArrayList indexs = new ArrayList();
ArrayList intervals = new ArrayList();
checkAnds(filter.getHome(), indexs, intervals, files, ctx);
int intervalSize = intervals.size();
if (intervalSize > 0 && intervalSize / 2 <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
//???ά???˵Ľ???????Ѿ???????
return cursor(fields, filter, ctx);
}
if (intervalSize == dataBlockCount * 2) {
//???ά???˵Ľ??ÿ?鶼??????,??û??????
intervals.clear();
intervalSize = 0;
}
int size = indexs.size();
if (size > 0) {
LongArray tempPos = null;
int i;
int maxRecordLen = 0;
Object []indexArray = new Object[size];
if (opt != null && opt.indexOf('u') != -1) {
//?????????ȼ?
indexs.toArray(indexArray);
} else {
//indexҪ???????ȼ?????
int j = 0;
i = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof Equals) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof Like) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if (node instanceof DotOperator) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
j = 0;
while (j < size) {
Object index = indexs.get(j++);
Object node = indexs.get(j++);
if ((!(node instanceof Equals))
&&(!(node instanceof Like))
&&(!(node instanceof DotOperator))) {
indexArray[i++] = index;
indexArray[i++] = node;
}
}
}
i = 0;
boolean isRow = this instanceof RowPhyTable;
long recCountOfSegment[] = null;
if (!isRow) {
recCountOfSegment = ((ColPhyTable)this).getSegmentInfo();
}
while (i < size) {
ITableIndex index = (ITableIndex)indexArray[i++];
Node node = (Node) indexArray[i++];
LongArray srcPos = index.select(new Expression(node), opt, ctx);
int len = index.getMaxRecordLen();
if (len > 0) {
maxRecordLen = len;
}
boolean sort = true;
if (isRow) {
tempPos = longArrayUnite(tempPos, srcPos.toArray(), index.getPositionCount(), sort);
if (tempPos.size() <= ITableIndex.MIN_ICURSOR_REC_COUNT) {
break;
}
} else {
long [] arr = srcPos.toArray();
if (sort) {
Arrays.sort(arr);
}
tempPos = longArrayUnite(tempPos, arr);
if (getBlockCount(tempPos, recCountOfSegment) <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
break;
}
}
if (intervalSize > 0) {
//????ά???˵Ľ??
tempPos = longArrayUnite(tempPos, intervals);
intervalSize = 0;//ֻ????1??
if (isRow) {
if (tempPos.size() <= ITableIndex.MIN_ICURSOR_REC_COUNT) {
break;
}
} else {
if (getBlockCount(tempPos, recCountOfSegment) <= ITableIndex.MIN_ICURSOR_BLOCK_COUNT) {
break;
}
}
}
}
ArrayList mrl = getModifyRecord(this, filter, ctx);
if (tempPos != null && tempPos.size() > 0) {
ICursor cs = new IndexCursor(this, fields, null, tempPos.toArray(), opt, ctx);
if (cs instanceof IndexCursor) {
((IndexCursor) cs).setModifyRecordList(mrl);
if (maxRecordLen != 0) {
((IndexCursor) cs).setRowBufferSize(maxRecordLen);
}
}
Select select = new Select(filter, null);
cs.addOperation(select, ctx);
return cs;
} else {
if (mrl == null) {
return null;
} else {
return new IndexCursor(this, fields, null, null, opt, ctx);
}
}
}
}
if (files == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
} else {
String[] filterFields;
if (filter.getHome() instanceof DotOperator) {
Node right = filter.getHome().getRight();
if (!(right instanceof Contain)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
String str = ((Contain)right).getParamString();
str = str.replaceAll("\\[", "");
str = str.replaceAll("\\]", "");
str = str.replaceAll(" ", "");
filterFields = str.split(",");
} else if (filter.getHome() instanceof Like) {
IParam sub1 = ((Like) filter.getHome()).getParam().getSub(0);
String f = (String) sub1.getLeafExpression().getIdentifierName();
filterFields = new String[]{f};
} else {
filterFields = getExpFields(filter, getColNames());
//List resultList = new ArrayList();
//filter.getUsedFields(ctx, resultList);
}
for (FileObject file : files) {
fileds = PhyTableIndex.readIndexFields(file);
if (PhyTableIndex.isCompatible(filterFields, fileds[0])) {
indexFile = file;
break;
}
}
if (filterFields == null || indexFile == null) {
//filter?в??????κ??ֶ? or ??????????
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
}
ITableIndex index = getTableMetaDataIndex(indexFile, fileds[0], fileds[1], true);
ArrayList mrl = getModifyRecord(this, filter, ctx);
ICursor cursor = index.select(filter, fields, opt, ctx);
if (cursor == null) {
if (mrl == null) {
return null;
} else {
cursor = new IndexCursor(this, fields, null, null, opt, ctx);
}
} else {
if (cursor instanceof IndexCursor) {
((IndexCursor) cursor).setModifyRecordList(mrl);
}
}
return cursor;
}
/**
* ȡ??????ʵ??
* @param indexFile ?????ļ?
* @param iname ??????
* @param isRead ?Ƕ???????????д????
* @return
*/
public ITableIndex getTableMetaDataIndex(FileObject indexFile, String iname, boolean isRead) {
String name = indexFile.getFileName().toLowerCase();
name += this.getTableName().toLowerCase();
if (isRead) {
SoftReference ref = cache.get(name);
ITableIndex ti = ref == null ? null : ref.get();
if (ti == null) {
if (!this.getGroupTable().getFile().exists()) {
return null;
}
try {
byte[] type = (byte[]) indexFile.read(6, 6, "b");
if (type[0] == 'x') {
ti = new PhyTableIndex(this, indexFile);
} else if (type[0] == 'h') {
ti = new TableHashIndex(this, indexFile);
} else if (type[0] == 'w') {
ti = new TableFulltextIndex(this, indexFile, null);
} else {
ti = new TableKeyValueIndex(this, indexFile);
}
//????iname?õ??????ֶ?
String []ifields = null;
String []vfields = null;
for (int i = 0; i < indexNames.length; i++) {
if (iname.equals(indexNames[i])) {
ifields = indexFields[i];
vfields = indexValueFields[i];
break;
}
}
ti.setName(iname);
ti.setFields(ifields, vfields);
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
cache.put(name, new SoftReference(ti));
}
return ti;
} else {
// ???????ļ?ɾ??????
cache.remove(name);
return null;
}
}
/**
* ȡ??????ʵ??
* @param indexFile ?????ļ?
* @return
*/
public ITableIndex getTableMetaDataIndex(FileObject indexFile, String []ifields, String []vfields, boolean isRead) {
File f = indexFile.getLocalFile().file();
String name = f.getAbsolutePath().toLowerCase();
if (!this.getGroupTable().getFile().exists()) {
return null;
}
if (isRead) {
SoftReference ref = cache.get(name);
ITableIndex ti = ref == null ? null : ref.get();
if (ti == null) {
if (!this.getGroupTable().getFile().exists()) {
return null;
}
try {
byte[] type = (byte[]) indexFile.read(6, 6, "b");
if (type[0] == 'x') {
ti = new PhyTableIndex(this, indexFile);
} else if (type[0] == 'h') {
ti = new TableHashIndex(this, indexFile);
} else if (type[0] == 'w') {
ti = new TableFulltextIndex(this, indexFile, null);
} else {
ti = new TableKeyValueIndex(this, indexFile);
}
ti.setFields(ifields, vfields);
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
cache.put(name, new SoftReference(ti));
}
return ti;
} else {
// ???????ļ?ɾ??????
cache.remove(name);
return null;
}
}
/**
* ?Ƿ????????ӱ?
* @param tableName
* @return
*/
public boolean isSubTable(String tableName) {
for (PhyTable table : tableList) {
if (tableName.equals(table.getTableName())) {
return true;
}
}
return false;
}
private void renameIndex(String oldName, String newName) {
if (indexNames == null) return;
int size = indexFields.length;
for (int i = 0; i < size; i++) {
for (int j = 0; j < indexFields[i].length; j++) {
if (oldName.equals(indexFields[i][j])) {
indexFields[i][j] = newName;
}
}
}
if (indexValueFields == null) return;
size = indexValueFields.length;
for (int i = 0; i < size; i++) {
if (indexValueFields[i] == null) continue;
for (int j = 0; j < indexValueFields[i].length; j++) {
if (oldName.equals(indexValueFields[i][j])) {
indexValueFields[i][j] = newName;
}
}
}
}
public void rename(String[] srcFields, String[] newFields, Context ctx) throws IOException {
getGroupTable().checkWritable();
//????µ????????Ƿ????ظ???
ArrayList list = new ArrayList();
for (String str : newFields) {
if (str != null) {
if (list.contains(str)) {
MessageManager mm = EngineMessage.get();
throw new RQException("rename" + mm.getMessage("function.invalidParam") + " : " + str);
} else {
list.add(str);
}
}
}
//???Ҫ?ĵ??????Ƿ????
NEXT:
for (String name : srcFields) {
for (String col : colNames) {
if (col.equals(name)) {
continue NEXT;
}
}
boolean find = false;
if (indexNames != null) {
for (int j = 0; j < indexNames.length; j++) {
if (name.equals(indexNames[j])) {
find = true;
break;
}
}
}
if (!find) {
MessageManager mm = EngineMessage.get();
throw new RQException("rename" + mm.getMessage("function.invalidParam") + " : " + name);
}
}
//?????ֲ??ܵ????ֶ???????????
for (String newField : newFields) {
for (String name : colNames) {
if (newField.equals(name)) {
MessageManager mm = EngineMessage.get();
throw new RQException("rename" + mm.getMessage("function.invalidParam") + " : " + newField);
}
}
if (indexNames != null) {
for (String name : indexNames) {
if (newField.equals(name)) {
MessageManager mm = EngineMessage.get();
throw new RQException("rename" + mm.getMessage("function.invalidParam") + " : " + newField);
}
}
}
}
//update colNames
int size = colNames.length;
int len = srcFields.length;
ColumnMetaData []columns = null;
if (this instanceof ColPhyTable) {
columns = ((ColPhyTable)this).getColumns();
}
for (int i = 0; i < len; i++) {
String name = srcFields[i];
for (int j = 0; j < size; j++) {
if (name.equals(colNames[j])) {
colNames[j] = newFields[i];
if (columns != null) {
columns[j].setColName(newFields[i]);
}
renameIndex(name, newFields[i]);//update index fields names
break;
}
}
}
//update segmentCol
if (segmentCol != null) {
for (int j = 0; j < len; j++) {
if (segmentCol.equals(srcFields[j])) {
segmentCol = newFields[j];
break;
}
}
}
if (indexNames != null) {
//update index names
String dir = groupTable.getFile().getAbsolutePath() + "_";
size = indexNames.length;
for (int i = 0; i < size; i++) {
String name = indexNames[i];
for (int j = 0; j < len; j++) {
if (name.equals(srcFields[j])) {
//???????ļ???
FileObject tmpFile = new FileObject(dir + tableName + "_" + name);
tmpFile.move(dir + tableName + "_" + newFields[j], null);
indexNames[i] = newFields[j];
}
}
}
}
groupTable.save();
init();
PhyTable tmd = getSupplementTable(false);
if (tmd != null) {
tmd.rename(srcFields, newFields, ctx);
}
}
// ȡ?ֲ?????ʽ??
public String getDistribute() {
return groupTable.getDistribute();
}
public abstract int getFirstBlockFromModifyRecord();
public abstract long resetByBlock(int block);
public void addCuboid(String cuboid) throws IOException {
int size = 0;
if (cuboids != null) {
size = cuboids.length;
}
String[] newCuboids = new String[size + 1];
if (size > 0) {
System.arraycopy(cuboids, 0, newCuboids, 0, size);
}
newCuboids[size] = cuboid;
cuboids = newCuboids;
groupTable.save();
}
/**
* ɾ??Cuboid
* @param cuboid
* @return
* @throws IOException
*/
public boolean deleteCuboid(String cuboid) throws IOException {
getGroupTable().checkWritable();
String[] oldFileName = cuboids;
FileObject tmpFile;
String dir = groupTable.getFile().getAbsolutePath() + "_";
if (oldFileName == null)
return false;
if (cuboid == null) {
for (String name : oldFileName) {
tmpFile = new FileObject(dir + tableName + Cuboid.CUBE_PREFIX + name);
tmpFile.delete();
}
cuboids = null;
} else {
tmpFile = new FileObject(dir + tableName + Cuboid.CUBE_PREFIX + cuboid);
if (!tmpFile.isExists())
return false;
int size = oldFileName.length;
int id = -1;
for (int i = 0; i < size; i++) {
if (oldFileName[i].equals(cuboid)) {
id = i;
break;
}
}
if (id < 0)
return false;
if (size == 1) {
this.cuboids = null;
} else {
this.cuboids = new String[size - 1];
int j = 0;
for (int i = 0; i < size; i++) {
if (i == id)
continue;
this.cuboids[j] = oldFileName[i];
j++;
}
}
tmpFile.delete();
}
groupTable.save();
return true;
}
public String[] getCuboids() {
return cuboids;
}
/**
* ????Cuboid
*/
public void updateCuboids() {
if (cuboids == null) return;
String dir = groupTable.getFile().getAbsolutePath() + "_";
for (String cuboid: cuboids) {
FileObject fo = new FileObject(dir + tableName + Cuboid.CUBE_PREFIX + cuboid);
if (!fo.isExists()) {
continue;
}
File file = fo.getLocalFile().file();
Cuboid table = null;
try {
table = new Cuboid(file, groupTable.ctx);
table.checkPassword("cuboid");
table.update(this);
table.close();
} catch (Exception e) {
if (table != null) table.close();
for (PhyTable tbl : tableList) {
tbl.close();
}
throw new RQException(e.getMessage(), e);
}
}
}
/**
* ?ؽ?Cuboid
* @param ctx
*/
public void resetCuboid(Context ctx) {
//Ԥ???鲻?ٸ?????????£?????ɾ??
// if (cuboids == null) return;
// String dir = groupTable.getFile().getAbsolutePath() + "_";
// for (String cuboid: cuboids) {
// FileObject fo = new FileObject(dir + tableName + Cuboid.CUBE_PREFIX + cuboid);
// if (!fo.isExists()) {
// continue;
// }
// File file = fo.getLocalFile().file();
// Cuboid table = null;
// Cuboid newTable = null;
// FileObject newFileObj = null;
// File newFile = null;
// try {
// newFileObj = new FileObject(file.getAbsolutePath());
// newFileObj = new FileObject(newFileObj.createTempFile(file.getName()));
// newFile = newFileObj.getLocalFile().file();
//
// table = new Cuboid(file, groupTable.ctx);//?????cuboid
// table.checkPassword("cuboid");
// newTable = new Cuboid(newFile, 0, table);
// newTable.checkPassword("cuboid");
// newTable.update(this);
// newTable.close();
// table.close();
// file.delete();
// newFile.renameTo(file);
// } catch (Exception e) {
// if (table != null) table.close();
// for (PhyTable tbl : tableList) {
// tbl.close();
// }
// if (newTable != null)
// newTable.close();
// if (newFile != null)
// newFile.delete();
// throw new RQException(e.getMessage(), e);
// }
// }
}
/**
* ?ϲ??α꣬????ʱҪ?鲢
* @param cs
* @param cs2
* @return
*/
ICursor merge(ICursor cs, ICursor cs2) {
String[] sortFields = ((IDWCursor) cs).getSortFields();
if (sortFields != null) {
int len = sortFields.length;
int []dims = new int[len];
DataStruct ds = cs.getDataStruct();
for (int i = 0; i < len ; i++) {
dims[i] = ds.getFieldIndex(sortFields[i]);
}
return new MergeCursor2(cs, cs2, dims, null, groupTable.ctx);
} else {
return new ConjxCursor(new ICursor[]{cs, cs2});
}
}
/**
* ͬ???ֶε???????·?α?ϳ?һ????·?α?
* @param cs1
* @param cs2
* @param sortFields
* @return
*/
MultipathCursors merge(MultipathCursors cs1, MultipathCursors cs2, String []sortFields) {
ICursor []cursors1 = cs1.getCursors();
ICursor []cursors2 = cs2.getCursors();
int count = cursors1.length;
ICursor []result = new ICursor[count];
int len = sortFields.length;
int []dims = new int[len];
DataStruct ds = cursors1[0].getDataStruct();
for (int i = 0; i < len ; i++) {
dims[i] = ds.getFieldIndex(sortFields[i]);
}
Context ctx = groupTable.ctx;
for (int i = 0; i < count; ++i) {
result[i] = new MergeCursor2(cursors1[i], cursors2[i], dims, null, ctx);
}
return new MultipathCursors(result, ctx);
}
MultipathCursors conj(MultipathCursors cs1, ICursor cs2) {
ICursor []cursors1 = cs1.getCursors();
int count = cursors1.length;
ICursor []result = new ICursor[count];
Context ctx = groupTable.ctx;
if (cs2 instanceof MultipathCursors) {
MultipathCursors mcs2 = (MultipathCursors)cs2;
ICursor []cursors2 = mcs2.getCursors();
int count2 = cursors2.length;
for (int i = 0; i < count; ++i) {
if (i < count2) {
result[i] = new ConjxCursor(new ICursor[]{cursors1[i], cursors2[i]});
} else {
result[i] = cursors1[i];
}
}
} else {
result[0] = new ConjxCursor(new ICursor[]{cursors1[0], cs2});
System.arraycopy(cursors1, 1, result, 1, count - 1);
}
return new MultipathCursors(result, ctx);
}
public PhyTable getSupplementTable(boolean isCreate) {
ComTable sgt = groupTable.getSupplement(isCreate);
if (sgt == null) {
return null;
}
PhyTable tmd = sgt.getBaseTable();
if (parent == null) {
return tmd;
} else {
return tmd.getAnnexTable(tableName);
}
}
/**
* ??ȡmcs?ķֶ??ֶ?
* @param mcs
* @param hashK trueȡkey?ֶΣ?falseȡ????1?ֶ?
* @return
*/
public static String[] getSegmentFields(MultipathCursors mcs, boolean hasK) {
ICursor []cursors = mcs.getParallelCursors();
for (ICursor cs : cursors) {
if (!(cs instanceof IDWCursor) && !(cs instanceof MergeCursor2)) {
MessageManager mm = EngineMessage.get();
throw new RQException("cursor" + mm.getMessage("dw.needMCursor"));
}
}
IDWCursor dwCursor;
if (cursors[0] instanceof IDWCursor) {
dwCursor = (IDWCursor)cursors[0];
} else if (cursors[0] instanceof MergeCursor2) {
dwCursor = (IDWCursor)((MergeCursor2)cursors[0]).getCursor1();
} else {
MessageManager mm = EngineMessage.get();
throw new RQException("cursor" + mm.getMessage("dw.needMCursor"));
}
String []dimFields;
if (hasK) {
//??kʱ????mcs?ĵ?һ??ά?ֶ?
dimFields = dwCursor.getSortFields();//dwCursor.getTableMetaData().getAllSortedColNames();
if (dimFields == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("cursor" + mm.getMessage("dw.needMCursor"));
}
String firstKeyField = dimFields[0];
if (dwCursor.getDataStruct().getFieldIndex(firstKeyField) == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException("cursor" + mm.getMessage("dw.needMCursor"));
} else {
return new String[] {firstKeyField};
}
} else {
dimFields = dwCursor.getSortFields();
}
if (dimFields == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("cursor" + mm.getMessage("dw.needMCursor"));
}
String segCol = dwCursor.getTableMetaData().getSegmentCol();
if (segCol != null) {
for (int i = dimFields.length - 1; i >= 0; --i) {
if (dimFields[i].equals(segCol)) {
String []tmp = new String[i + 1];
System.arraycopy(dimFields, 0, tmp, 0, i + 1);
return tmp;
}
}
}
return dimFields;
}
public ICursor cursor() {
return cursor(null, null, null, null, null, null, null, groupTable.ctx);
}
public ICursor cursor(String []fields) {
return cursor(null, fields, null, null, null, null, null, groupTable.ctx);
}
public ICursor cursor(String []fields, Expression filter, Context ctx) {
return cursor(null, fields, filter, null, null, null, null, ctx);
}
/**
* ????src?????????Ľṹ
* @param src
*/
public void dupIndexAdnCuboid(PhyTable src) {
String []indexNames = src.indexNames;
if (indexNames != null) {
this.indexNames = indexNames;
this.indexFields = src.indexFields;
this.indexValueFields = src.indexValueFields;
String dir = src.getGroupTable().getFile().getAbsolutePath() + "_";
for (String iname : indexNames) {
if (iname != null) {
FileObject srcIndexFile = new FileObject(dir + src.getTableName() + "_" + iname);
ITableIndex srcIndex = src.getTableMetaDataIndex(srcIndexFile, iname, true);
srcIndex.dup(this);
}
}
}
String cuboids[] = src.cuboids;
if (cuboids != null) {
this.cuboids = cuboids;
String srcDir = src.groupTable.getFile().getAbsolutePath() + "_";
String dir = groupTable.getFile().getAbsolutePath() + "_";
for (String cuboid: cuboids) {
FileObject srcFo = new FileObject(srcDir + src.tableName + Cuboid.CUBE_PREFIX + cuboid);
File srcFile = srcFo.getLocalFile().file();
Cuboid srcCuboid = null;
FileObject fo = new FileObject(dir + tableName + Cuboid.CUBE_PREFIX + cuboid);
File file = fo.getLocalFile().file();
Cuboid table = null;
try {
srcCuboid = new Cuboid(srcFile, groupTable.ctx);
table = srcCuboid.dup(file);
table.close();
srcCuboid.close();
} catch (Exception e) {
if (table != null) table.close();
if (srcCuboid != null) srcCuboid.close();
for (PhyTable tbl : tableList) {
tbl.close();
}
throw new RQException(e.getMessage(), e);
}
}
}
}
abstract public Object[] getMaxMinValue(String column) throws IOException;
public int getDeleteFieldIndex(Expression []exps, String []fields) {
if (getGroupTable().hasDeleteKey()) {
//ɾ??????????????
String[] colNames = this.colNames;
String[] keyNames = getAllKeyColNames();
if (keyNames == null) return -1;
int keyCount = keyNames.length;
int colCount = colNames.length;
if (keyCount >= colCount) return -1;
String deleteKey = colNames[keyCount];
if (exps == null) {
//??ʱ??fieldsΪ
if (fields == null) {
//ȫȡ?????
return keyCount;
}
for (int i = 0, len = fields.length; i < len; i++) {
if (fields[i] != null && fields[i].equals(deleteKey)) {
return i;
}
}
} else {
for (int i = 0, len = exps.length; i < len; i++) {
if (exps[i] != null && exps[i].getHome() instanceof UnknownSymbol && exps[i].getIdentifierName().equals(deleteKey)) {
return i;
}
}
}
}
return -1;
}
}