com.scudata.dw.TableKeyValueIndex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of esproc Show documentation
Show all versions of esproc Show documentation
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.dw;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import com.scudata.array.IArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.Env;
import com.scudata.dm.FileObject;
import com.scudata.dm.LongArray;
import com.scudata.dm.ObjectReader;
import com.scudata.dm.ObjectWriter;
import com.scudata.dm.RandomObjectWriter;
import com.scudata.dm.RandomOutputStream;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.*;
import com.scudata.dm.op.New;
import com.scudata.expression.*;
import com.scudata.expression.fn.string.Like;
import com.scudata.expression.mfn.sequence.Contain;
import com.scudata.expression.operator.*;
import com.scudata.resources.EngineMessage;
import com.scudata.util.EnvUtil;
import com.scudata.util.Variant;
/**
* KV????
* key-value??????ֱ?Ӵ?ָ?????ֶ?ֵ??????Դ?ļ??ļ?¼??ַ
* @author runqian
*
*/
public class TableKeyValueIndex implements ITableIndex {
private static final int NULL = -1;
private static final int EQ = 0; // ????
private static final int GE = 1; // ???ڵ???
private static final int GT = 2; // ????
private static final int LE = 3; // С?ڵ???
private static final int LT = 4; // С??
private static final int LIKE = 5;
private static final int BUFFER_SIZE = 1024;
private static final int BLOCK_START = -1;
protected static final int BLOCK_END = -2;
private static final int BLOCK_VALUE_START = -3;
public static final int MAX_LEAF_BLOCK_COUNT = 1000;//Ҷ?ӽ???????¼??
public static final int MAX_INTER_BLOCK_COUNT = 1000;//?м????????¼??
public static final int MAX_ROOT_BLOCK_COUNT = 1000;//
public static final int MAX_SEC_RECORD_COUNT = 100000;//max count of index2
public static final int FETCH_SIZE = 20;//һ??ȡ20?????
private long recordCount = 0; // Դ??¼??
private long index1RecordCount = 0; // ????1??¼??
private long index1EndPos = 0; // ????1????ʱԴ?ļ???¼????λ??
protected String []ifields; // ?????ֶ?????
protected String []vfields; // value?ֶ?????
private String name;
protected PhyTable srcTable;
protected FileObject indexFile;
// ????ʱʹ??
private Object []rootBlockMaxVals; // ÿһ??????ֵ
private long []rootBlockPos; // ÿһ???λ??
private long internalBlockCount = 0;
private Object [][]internalAllBlockMaxVals; // ?м?ڵ????п?????ֵ
private long [][]internalAllBlockPos; // ?м?ڵ????п??λ?õĻ???
private Object []rootBlockMaxVals2; // ÿһ??????ֵ
private long []rootBlockPos2; // ÿһ???λ??
private long internalBlockCount2 = 0;
private Object [][]internalAllBlockMaxVals2; // ?м?ڵ????п?????ֵ
private long [][]internalAllBlockPos2; // ?м?ڵ????п??λ??
private long rootItPos = 0;//1st root node pos
private long rootItPos2 = 0;// sec root node pos
private long indexPos = 0;//sec index pos
private long indexPos2 = 0;//sec index pos
//?????㻺?????????internalAllBlockPos??Ҫ?????
private transient byte [][][]cachedBlockReader;
private transient byte [][][]cachedBlockReader2;
private Expression filter;
protected transient int vfieldsCount;//ÿһ????????¼??value?ֶθ???
private class FieldFilter {
private Object startVal;
private Object endVal;
private int startSign = NULL;
private int endSign = NULL;
}
private class BlockInfo {
private Object []internalBlockMaxVals;
private long []internalBlockPos;
}
/**
* ???ڽ???????ʱȡ??????????????
* @author runqian
*
*/
private class CTableCursor extends ICursor {
public static final String POS_FIELDNAME = "rq_file_seq";
private ColPhyTable table;
private String []fields;//?????ֶ?
private String []valueFields;//value ?ֶ?
private Expression filter;
private DataStruct ds;
private BlockLinkReader rowCountReader;
private BlockLinkReader []colReaders;
private ObjectReader []segmentReaders;
private ColumnMetaData []columns;
private int dataBlockCount;
private int curBlock = 0;
private Sequence cache;
private boolean isClosed = false;
private long curNum = 0;//ȫ?ּ?¼??
public CTableCursor(PhyTable table, String []fields, String []valueFields, Context ctx, Expression filter) {
this.table = (ColPhyTable) table;
this.fields = fields;
this.valueFields = valueFields;
this.ctx = ctx;
this.filter = filter;
init();
}
private void init() {
dataBlockCount = table.getDataBlockCount();
if (fields == null || valueFields == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("index" + mm.getMessage("function.invalidParam"));
}
ArrayList list = new ArrayList();
for (String f : fields) {
list.add(f);
}
for (String f : valueFields) {
if (!list.contains(f)) {
list.add(f);
}
}
int size = list.size();
fields = new String[size];
list.toArray(fields);
//??????????ʽʱҪȡ??????
if (filter != null) {
columns = table.getColumns();
} else {
columns = table.getColumns(fields);
}
list.add(POS_FIELDNAME);//??һ??α??
size = list.size();
fields = new String[size];
list.toArray(fields);
ds = new DataStruct(fields);
int colCount = columns.length;
rowCountReader = table.getSegmentReader();
colReaders = new BlockLinkReader[colCount];
for (int i = 0; i < colCount; ++i) {
colReaders[i] = columns[i].getColReader(true);
}
segmentReaders = new ObjectReader[colCount];
for (int i = 0; i < colCount; ++i) {
segmentReaders[i] = columns[i].getSegmentReader();
}
}
protected Sequence get(int n) {
if (isClosed || n < 1) {
return null;
}
Sequence cache = this.cache;
if (cache != null) {
int len = cache.length();
if (len > n) {
this.cache = cache.split(n + 1);
return cache;
} else if (len == n) {
this.cache = null;
return cache;
}
} else {
cache = new Table(ds, n);
}
int curBlock = this.curBlock;
int dataBlockCount = this.dataBlockCount;
BlockLinkReader rowCountReader = this.rowCountReader;
BlockLinkReader []colReaders = this.colReaders;
int colCount = colReaders.length;
BufferReader []bufReaders = new BufferReader[colCount];
DataStruct ds = this.ds;
IArray mems = cache.getMems();
this.cache = null;
ComputeStack stack = null;
Expression filter = this.filter;
DataStruct fullDs = null;
String []fields = this.fields;
int fieldsLen = fields.length - 1;
int []fieldsIndex = new int[fieldsLen];
if (filter != null) {
stack = ctx.getComputeStack();
String[] fullFields = table.getColNames();
fullDs = new DataStruct(fullFields);
for (int i = 0; i < fieldsLen; ++i) {
fieldsIndex[i] = fullDs.getFieldIndex(fields[i]);
}
}
try {
while (curBlock < dataBlockCount) {
curBlock++;
if (filter != null) {
int recordCount = rowCountReader.readInt32();
for (int f = 0; f < colCount; ++f) {
bufReaders[f] = colReaders[f].readBlockData(recordCount);
}
int i;
for (i = 0; i < recordCount; ++i) {
Record r = new Record(ds);
Record cmpr = new Record(fullDs);
++curNum;
for (int f = 0; f < colCount; ++f) {
cmpr.setNormalFieldValue(f, bufReaders[f].readObject());
}
stack.push(cmpr);
Object b = filter.calculate(ctx);
if (Variant.isTrue(b)) {
for (int f = 0; f < fieldsLen; ++f) {
r.setNormalFieldValue(f, cmpr.getFieldValue(fieldsIndex[f]));
}
r.setNormalFieldValue(fieldsLen, new Long(curNum));
mems.add(r);
}
stack.pop();
if (mems.size() == n) {
i++;
break;
}
}
if (mems.size() == n) {
Table tmp = new Table(ds, ICursor.FETCHCOUNT);
this.cache = tmp;
mems = tmp.getMems();
for (; i < recordCount; ++i) {
Record r = new Record(ds);
Record cmpr = new Record(fullDs);
++curNum;
for (int f = 0; f < colCount; ++f) {
cmpr.setNormalFieldValue(f, bufReaders[f].readObject());
}
stack.push(cmpr);
Object b = filter.calculate(ctx);
if (Variant.isTrue(b)) {
for (int f = 0; f < fieldsLen; ++f) {
r.setNormalFieldValue(f, cmpr.getFieldValue(fieldsIndex[f]));
}
r.setNormalFieldValue(fieldsLen, new Long(curNum));
mems.add(r);
}
stack.pop();
if (mems.size() == n) {
i++;
break;
}
}
if (mems.size() == 0) this.cache = null;
break;
}
continue;
}
int recordCount = rowCountReader.readInt32();
for (int f = 0; f < colCount; ++f) {
bufReaders[f] = colReaders[f].readBlockData(recordCount);
}
int diff = n - cache.length();
if (recordCount > diff) {
int i = 0;
for (; i < diff; ++i) {
Record r = new Record(ds);
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, bufReaders[f].readObject());
}
r.setNormalFieldValue(colCount, new Long(++curNum));
mems.add(r);
}
Table tmp = new Table(ds, ICursor.FETCHCOUNT);
this.cache = tmp;
mems = tmp.getMems();
for (; i < recordCount; ++i) {
Record r = new Record(ds);
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, bufReaders[f].readObject());
}
r.setNormalFieldValue(colCount, new Long(++curNum));
mems.add(r);
}
break;
} else {
for (int i = 0; i < recordCount; ++i) {
Record r = new Record(ds);
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, bufReaders[f].readObject());
}
r.setNormalFieldValue(colCount, new Long(++curNum));
mems.add(r);
}
if (diff == recordCount) {
break;
}
}
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
this.curBlock = curBlock;
if (cache.length() > 0) {
return cache;
} else {
return null;
}
}
protected long skipOver(long n) {
return 0;
}
public long seek(long n) {
if (isClosed || n < 1) {
return 0;
}
int curBlock = this.curBlock;
int dataBlockCount = this.dataBlockCount;
long skipCount = 0;
if (cache != null) {
skipCount = cache.length();
if (skipCount > n) {
this.cache = cache.split((int)n + 1);
return n;
} else if (skipCount == n) {
this.cache = null;
return n;
} else {
this.cache = null;
}
}
BlockLinkReader rowCountReader = this.rowCountReader;
BlockLinkReader []colReaders = this.colReaders;
int colCount = colReaders.length;
long pos;
try {
//seek to first block
for(int i = 0; i < colCount; i++) {
pos = segmentReaders[i].readLong40();
if (columns[i].hasMaxMinValues()) {
segmentReaders[i].skipObject();
segmentReaders[i].skipObject();
segmentReaders[i].skipObject();
}
colReaders[i].seek(pos);
}
while (curBlock < dataBlockCount) {
curBlock++;
int recordCount = rowCountReader.readInt32();
long diff = n - skipCount;
if (recordCount > diff) {
//never run to here
diff = diff / 0;
} else {
for(int i = 0; i < colCount; i++) {
pos = segmentReaders[i].readLong40();
if (columns[i].hasMaxMinValues()) {
segmentReaders[i].skipObject();
segmentReaders[i].skipObject();
segmentReaders[i].skipObject();
}
colReaders[i].seek(pos);
}
skipCount += recordCount;
if (diff == recordCount) {
break;
}
}
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
curNum += skipCount;
this.curBlock = curBlock;
return skipCount;
}
public void close() {
super.close();
isClosed = true;
cache = null;
try {
if (segmentReaders != null) {
for (ObjectReader reader : segmentReaders) {
reader.close();
}
}
} catch (Exception e) {
throw new RQException(e.getMessage(), e);
} finally {
rowCountReader = null;
colReaders = null;
segmentReaders = null;
}
}
public boolean reset() {
close();
isClosed = false;
curBlock = 0;
return true;
}
}
private class RTableCursor extends ICursor {
public static final String POS_FIELDNAME = "rq_file_seq";
private RowPhyTable table;
private String []fields;
private String []valueFields;
private Expression filter;
private DataStruct ds;
private BlockLinkReader rowReader;
private ObjectReader segmentReader;
private ObjectReader rowDataReader;
private int dataBlockCount;
private int curBlock = 0;
private Sequence cache;
private boolean isClosed = false;
private boolean isPrimaryTable; // ?Ƿ?????
//private RTableCursor parentCursor;//?????α?
//private Record curPkey;
//private long pseq;
private DataStruct fullDs;
private int []fieldsIndex;
private boolean []needRead;
public RTableCursor(PhyTable table, String []fields, String []valueFields, Context ctx, Expression filter) {
this.table = (RowPhyTable) table;
this.fields = fields;
this.valueFields = valueFields;
this.ctx = ctx;
this.filter = filter;
init();
}
//filter????ֶ?Ҫ??????
private void parseFilter(Node node) {
if (node == null) return;
if (node instanceof UnknownSymbol) {
String f = ((UnknownSymbol) node).getName();
int id = fullDs.getFieldIndex(f);
if (id >= 0) needRead[id] = true;
return;
}
parseFilter(node.getLeft());
parseFilter(node.getRight());
}
private void init() {
dataBlockCount = table.getDataBlockCount();
ArrayList list = new ArrayList();
for (String f : fields) {
list.add(f);
}
for (String f : valueFields) {
if (!list.contains(f)) {
list.add(f);
}
}
list.add(POS_FIELDNAME);//??һ??α??
int size = list.size();
fields = new String[size];
list.toArray(fields);
rowReader = table.getRowReader(true);
rowDataReader = new ObjectReader(rowReader, table.groupTable.getBlockSize() - ComTable.POS_SIZE);
segmentReader = table.getSegmentObjectReader();
isPrimaryTable = table.parent == null;
ds = new DataStruct(fields);
if (!isPrimaryTable) {
//TODO
}
int colCount = this.fields.length;
String[] fullFields = table.getAllColNames();
fieldsIndex = new int[colCount];
needRead = new boolean[fullFields.length];
fullDs = new DataStruct(fullFields);
for (int i = 0; i < colCount; ++i) {
int id = fullDs.getFieldIndex(fields[i]);
fieldsIndex[i] = id;
if (id >= 0) needRead[id] = true;
}
if (filter != null) {
parseFilter(filter.getHome());
}
}
protected Sequence get(int n) {
if (isClosed || n < 1) {
return null;
}
Sequence cache = this.cache;
if (cache != null) {
int len = cache.length();
if (len > n) {
this.cache = cache.split(n + 1);
return cache;
} else if (len == n) {
this.cache = null;
return cache;
}
} else {
cache = new Table(ds, n);
}
int curBlock = this.curBlock;
int dataBlockCount = this.dataBlockCount;
ObjectReader segmentReader = this.segmentReader;
int colCount = this.fields.length - 1;
String[] fullFields = table.getAllColNames();
int allCount = fullFields.length;
int keyCount = table.getAllSortedColNamesLength();
DataStruct ds = this.ds;
IArray mems = cache.getMems();
this.cache = null;
ComputeStack stack = null;
Expression filter = this.filter;
DataStruct fullDs = this.fullDs;
int []fieldsIndex = this.fieldsIndex;
boolean needRead[] = this.needRead;
Object []values = new Object[allCount];
ObjectReader rowDataReader = this.rowDataReader;
long seq;//α??
@SuppressWarnings("unused")
long pseq = 0;//????α??
boolean isPrimaryTable = this.isPrimaryTable;
int startIndex;
if (isPrimaryTable) {
startIndex = 0;
} else {
startIndex = table.parent.getSortedColNames().length;
}
if (filter != null) {
stack = ctx.getComputeStack();
}
try {
while (curBlock < dataBlockCount) {
curBlock++;
rowDataReader.readInt32();
if (filter != null) {
int recordCount = segmentReader.readInt32();
segmentReader.readLong40();
for (int i = 0; i < keyCount; ++i) {
segmentReader.skipObject();
segmentReader.skipObject();
}
if (recordCount == 0) {
rowDataReader.skipObject();
continue;
}
int i;
for (i = 0; i < recordCount; ++i) {
Record r = new Record(ds);
Record cmpr = new Record(fullDs);
seq = rowDataReader.readLong();
if (!isPrimaryTable) {
pseq = rowDataReader.readLong();//????
}
for (int f = startIndex; f < allCount; ++f) {
if (needRead[f])
cmpr.setNormalFieldValue(f, rowDataReader.readObject());
else
rowDataReader.skipObject();
}
stack.push(cmpr);
Object b = filter.calculate(ctx);
if (Variant.isTrue(b)) {
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, cmpr.getFieldValue(fieldsIndex[f]));
}
r.setNormalFieldValue(colCount, seq);
mems.add(r);
}
stack.pop();
if (mems.size() == n) {
i++;
break;
}
}
if (mems.size() == n) {
Table tmp = new Table(ds, ICursor.FETCHCOUNT);
this.cache = tmp;
mems = tmp.getMems();
for (; i < recordCount; ++i) {
Record r = new Record(ds);
Record cmpr = new Record(fullDs);
seq = rowDataReader.readLong();
if (!isPrimaryTable) {
pseq = rowDataReader.readLong();//????????
}
for (int f = startIndex; f < allCount; ++f) {
if (needRead[f])
cmpr.setNormalFieldValue(f, rowDataReader.readObject());
else
rowDataReader.skipObject();
}
stack.push(cmpr);
Object b = filter.calculate(ctx);
if (Variant.isTrue(b)) {
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, cmpr.getFieldValue(fieldsIndex[f]));
}
r.setNormalFieldValue(colCount, seq);
mems.add(r);
}
stack.pop();
if (mems.size() == n) {
i++;
break;
}
}
if (mems.size() == 0) this.cache = null;
break;
}
continue;
}
int recordCount = segmentReader.readInt32();
segmentReader.readLong40();
for (int i = 0; i < keyCount; ++i) {
segmentReader.skipObject();
segmentReader.skipObject();
}
if (recordCount == 0) {
rowDataReader.skipObject();
continue;
}
int diff = n - cache.length();
if (recordCount > diff) {
int i = 0;
for (; i < diff; ++i) {
Record r = new Record(ds);
seq = rowDataReader.readLong();
if (!isPrimaryTable) {
pseq = rowDataReader.readLong();//????
}
for (int f = startIndex; f < allCount; ++f) {
if (needRead[f])
values[f] = rowDataReader.readObject();
else
rowDataReader.skipObject();
}
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, values[fieldsIndex[f]]);
}
r.setNormalFieldValue(colCount, seq);
mems.add(r);
}
Table tmp = new Table(ds, ICursor.FETCHCOUNT);
this.cache = tmp;
mems = tmp.getMems();
for (; i < recordCount; ++i) {
Record r = new Record(ds);
seq = rowDataReader.readLong();
if (!isPrimaryTable) {
pseq = rowDataReader.readLong();//????????
}
for (int f = startIndex; f < allCount; ++f) {
if (needRead[f])
values[f] = rowDataReader.readObject();
else
rowDataReader.skipObject();
}
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, values[fieldsIndex[f]]);
}
r.setNormalFieldValue(colCount, seq);
mems.add(r);
}
break;
} else {
for (int i = 0; i < recordCount; ++i) {
Record r = new Record(ds);
seq = rowDataReader.readLong();
if (!isPrimaryTable) {
pseq = rowDataReader.readLong();//????
}
for (int f = startIndex; f < allCount; ++f) {
if (needRead[f])
values[f] = rowDataReader.readObject();
else
rowDataReader.skipObject();
}
for (int f = 0; f < colCount; ++f) {
r.setNormalFieldValue(f, values[fieldsIndex[f]]);
}
r.setNormalFieldValue(colCount, seq);
mems.add(r);
}
if (diff == recordCount) {
break;
}
}
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
this.curBlock = curBlock;
if (cache.length() > 0) {
return cache;
} else {
return null;
}
}
protected long skipOver(long n) {
if (isClosed || n < 1) {
return 0;
}
boolean isPrimaryTable = this.isPrimaryTable;
int curBlock = this.curBlock;
int dataBlockCount = this.dataBlockCount;
ObjectReader segmentReader = this.segmentReader;
int allCount = table.getColNames().length;
int keyCount = table.getAllSortedColNamesLength();
int skipCount = 0;
ObjectReader rowDataReader = this.rowDataReader;
try {
while (curBlock < dataBlockCount) {
curBlock++;
rowDataReader.readInt32();
int recordCount = segmentReader.readInt32();
segmentReader.readLong40();
for (int i = 0; i < keyCount; ++i) {
segmentReader.skipObject();
segmentReader.skipObject();
}
if (recordCount == 0) {
rowDataReader.skipObject();
continue;
}
for (int i = 0; i < recordCount; ++i) {
rowDataReader.readLong();
if (!isPrimaryTable) {
rowDataReader.readLong();//????
}
for (int f = 0; f < allCount; ++f) {
rowDataReader.readObject();
}
}
skipCount += recordCount;
if (n == skipCount) {
break;
}
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
this.curBlock = curBlock;
return skipCount;
}
public long seek(long n) {
return skipOver(n);
}
public void close() {
super.close();
isClosed = true;
cache = null;
try {
segmentReader.close();
} catch (Exception e) {
throw new RQException(e.getMessage(), e);
} finally {
rowReader = null;
}
}
public boolean reset() {
close();
isClosed = false;
curBlock = 0;
return true;
}
}
public TableKeyValueIndex(PhyTable table, String indexName) {
table.getGroupTable().checkWritable();
this.srcTable = table;
this.name = indexName;
String dir = table.getGroupTable().getFile().getAbsolutePath() + "_";
indexFile = new FileObject(dir + table.getTableName() + "_" + indexName);
}
public TableKeyValueIndex(PhyTable table, FileObject indexFile) {
this.srcTable = table;
this.indexFile = indexFile;
}
private void writeHeader(ObjectWriter writer) throws IOException {
writer.write('r');
writer.write('q');
writer.write('d');
writer.write('w');
writer.write('i');
writer.write('d');
writer.write('v');
writer.write(new byte[32]);
writer.writeLong64(recordCount);
writer.writeLong64(index1EndPos);
writer.writeLong64(index1RecordCount);
writer.writeLong64(rootItPos);// ָ??root1 info ??ʼλ??
writer.writeLong64(rootItPos2);// ָ??root2 info ??ʼλ??
writer.writeLong64(indexPos);// 1st index ??ʼλ??
writer.writeLong64(indexPos2);// second index ??ʼλ??
writer.writeStrings(ifields);
writer.writeStrings(vfields);
if (filter != null) {
writer.write(1);
writer.writeUTF(filter.toString());
} else {
writer.write(0);
}
}
private void updateHeader(RandomObjectWriter writer) throws IOException {
writer.position(39);
writer.writeLong64(recordCount);
writer.writeLong64(index1EndPos);
writer.writeLong64(index1RecordCount);
writer.writeLong64(rootItPos);// ָ??root1 info ??ʼλ??
writer.writeLong64(rootItPos2);// ָ??root2 info ??ʼλ??
writer.writeLong64(indexPos);// 1st index ??ʼλ??
writer.writeLong64(indexPos2);// second index ??ʼλ??
}
private void readHeader(ObjectReader reader) throws IOException {
if (reader.read() != 'r' || reader.read() != 'q' ||
reader.read() != 'd' || reader.read() != 'w' ||
reader.read() != 'i' || reader.read() != 'd' || reader.read() != 'v') {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("license.fileFormatError"));
}
reader.readFully(new byte[32]);
recordCount = reader.readLong64();
index1EndPos = reader.readLong64();
index1RecordCount = reader.readLong64();
rootItPos = reader.readLong64();
rootItPos2 = reader.readLong64();
indexPos = reader.readLong64();
indexPos2 = reader.readLong64();
reader.readStrings();//ifields
reader.readStrings();//vfields
if (reader.read() != 0) {
filter = new Expression(reader.readUTF());
} else {
filter = null;
}
}
public void setFields(String[] ifields, String[] vfields) {
this.ifields = ifields;
this.vfields = vfields;
if (vfields != null) {
vfieldsCount = vfields.length + 1;//????һ??α??
}
}
/**
* ????????
* ?????ļ??ṹ????rqit?? + 8byte + Դ?ļ???¼?? + Դ?ļ?????λ?? + [?????ֶ?] + Դ?ļ??? +
* BLOCK_START +[n + value + pos1,...,posn],... BLOCK_END + ?????? + ??????λ??
* @param fields ?????ֶ?
* @param valueFields ֵ?ֶ?
* @param opt
* @param ctx
* @param filter
*/
public void create(String []fields, String []valueFields, String opt, Context ctx, Expression filter) {
int icount = fields.length;
boolean isAppend = false;//?ӻ????½?
boolean isAdd = true;//?Ƿ???Ҫ??????????table
boolean isReset = false;//?ؽ?
valueFields = checkValueFields(fields, valueFields);
if (indexFile.size() > 0) {
if ((opt == null) ||(opt != null && opt.indexOf('a') == -1)) {
MessageManager mm = EngineMessage.get();
if (name == null) {
throw new RQException(indexFile.getFileName() + " " + mm.getMessage("dw.indexNameAlreadyExist"));
} else {
throw new RQException(name + " " + mm.getMessage("dw.indexNameAlreadyExist"));
}
}
}
while (opt != null && opt.indexOf('a') != -1 && indexFile.size() > 0) {
isAppend = true;
isAdd = false;
isReset = opt.indexOf('r') != -1;
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
readHeader(reader);
filter = this.filter;
if (recordCount - index1RecordCount > MAX_SEC_RECORD_COUNT || isReset) {
isAppend = false;
rootItPos2 = 0;
indexPos2 = 0;
rootItPos = 0;
indexPos = 0;
index1EndPos = 0;
reader.close();
indexFile.delete();
break;
}
if ((fields.length != ifields.length) || (0 != Variant.compareArrays(fields, ifields))) {
MessageManager mm = EngineMessage.get();
throw new RQException("index" + mm.getMessage("engine.dsNotMatch"));
}
ArrayList cursorList;
if (srcTable instanceof RowPhyTable) {
cursorList = sortRow(fields, valueFields, ctx, filter);
} else {
cursorList = sortCol(fields, valueFields, ctx, filter);
}
int size = cursorList.size();
if (size == 0) {
return;
} else if (size == 1) {
createIndexTable(cursorList.get(0), indexFile, true);
} else {
ICursor []cursors = new ICursor[cursorList.size()];
cursorList.toArray(cursors);
Expression []exps = new Expression[icount];
for (int i = 0; i < icount; ++i) {
exps[i] = new Expression(ctx, "#" + (i + 1));
}
ICursor cursor = new MergesCursor(cursors, exps, ctx);
createIndexTable(cursor, indexFile, true);
}
srcTable.getTableMetaDataIndex(indexFile, null, false);//?Ӻ?Ҫ???cache
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
break;
}
if (!isAppend) {
this.filter = filter;
FileObject tmpFile;
boolean needDelete = false;
if (indexFile.isExists()) {
String tmpFileName = indexFile.createTempFile("tmp");
tmpFile = new FileObject(tmpFileName);
tmpFile.delete();
needDelete = true;
} else {
tmpFile = indexFile;
}
//this.endPos = 0;
this.recordCount = 0;
index1RecordCount = 0;
ArrayList cursorList;
if (srcTable instanceof RowPhyTable) {
cursorList = sortRow(fields, valueFields, ctx, filter);
} else {
cursorList = sortCol(fields, valueFields, ctx, filter);
}
int size = cursorList == null ? 0 : cursorList.size();
if (size == 0) {
createIndexTable(null, tmpFile, false);
} else if (size == 1) {
createIndexTable(cursorList.get(0), tmpFile, false);
} else {
ICursor []cursors = new ICursor[size];
cursorList.toArray(cursors);
Expression []exps = new Expression[icount];
for (int i = 0; i < icount; ++i) {
exps[i] = new Expression(ctx, "#" + (i + 1));
}
ICursor cursor = new MergesCursor(cursors, exps, ctx);
createIndexTable(cursor, tmpFile, false);
}
srcTable.getTableMetaDataIndex(indexFile, null, false);//?Ӻ?Ҫ???cache
if (needDelete) {
indexFile.delete();
tmpFile.move(indexFile.getFileName(), null);
}
if (opt != null && opt.indexOf('U') != -1) {
isAdd = false;
}
try {
if (isAdd) {
srcTable.addIndex(name, ifields, vfields);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
}
}
}
private String[] checkValueFields(String[] ifields, String[] vfields) {
ArrayList list = new ArrayList();
Next:
for (String vfield : vfields) {
for (String ifield : ifields) {
if (vfield.equals(ifield))
continue Next;
}
list.add(vfield);
}
int count = list.size();
String[] retFields = new String[count];
list.toArray(retFields);
return retFields;
}
//???mems???????ĸ???
private int getGroupNum(IArray mems, int from, int fcount) {
int len = mems.size();
int count = 1;
Record r;
r = (Record)mems.get(from);
Object []firstVals = r.getFieldValues();
for (int i = from + 1; i <= len; i++) {
r = (Record)mems.get(i);
Object []vals = r.getFieldValues();
int cmp = Variant.compareArrays(firstVals, vals, fcount);
if (cmp == 0) {
count++;
} else {
break;
}
}
return count;
}
private void createIndexTable(ICursor cursor, FileObject indexFile, boolean isAppends) {
RandomOutputStream os = indexFile.getRandomOutputStream(true);
RandomObjectWriter writer = new RandomObjectWriter(os);
long perCount = MAX_LEAF_BLOCK_COUNT;
ArrayList maxValues = new ArrayList();
Record []rootMaxValues;// root??????????ֵ
long []positions; // internal?????????ļ??е???ʼλ??
long []rootPositions; // root?????????ļ??е???ʼλ??
int blockCount = 0; // ????????
long itPos;
int recCount = 0;
int icount = ifields.length;
int vcount = icount + vfields.length + 1;//????һ??α??
Context ctx = new Context();
Expression []ifs = new Expression[icount];
for (int i = 0; i < icount; ++i) {
ifs[i] = new Expression("#" + (i + 1));
}
//????Ƿ??Ƕ?????????????
boolean isPrimaryKey = false;
// String[] keyNames = srcTable.getAllSortedColNames();
// if (srcTable.hasPrimaryKey && keyNames != null && ifields.length == keyNames.length) {
// isPrimaryKey = true;
// for (int i = 0, len = ifields.length; i < len; ++i) {
// if (!ifields[i].equals(keyNames[i])) {
// isPrimaryKey = false;
// break;
// }
// }
// }
RowBufferWriter bufferWriter = null;
long blockValueStartPos = 0;
ArrayList posList1 = new ArrayList(1024);
ArrayList posList2 = new ArrayList(1024);
try {
if (isAppends) {
indexFile.setFileSize(indexPos2);
writer.position(indexPos2);
} else {
writer.position(0);
writeHeader(writer);
if (cursor == null) {
writer.close();
return;
}
}
Sequence table;
Record r = null;
if (isPrimaryKey) {
table = cursor.fetch(MAX_LEAF_BLOCK_COUNT * FETCH_SIZE);
if (table == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("index" + mm.getMessage("function.invalidParam"));
}
while (table != null) {
//ÿ??д20??
IArray mems = table.getMems();
int rest = mems.size();
recCount += rest;
if (rest == 0) break;
int p = 1;
for (int c = 0; c < FETCH_SIZE; c++) {
writer.writeInt(BLOCK_START);
//??д0????????д??ʵֵ
blockValueStartPos = writer.position();
posList1.add(blockValueStartPos);
writer.writeLong40(0);
bufferWriter = new RowBufferWriter(null);//дvalue??buffer
int count = rest >= MAX_LEAF_BLOCK_COUNT ? MAX_LEAF_BLOCK_COUNT : rest;
rest -= count;
for (int j = 0; j < count; j++) {
r = (Record)mems.get(p++);
writer.writeInt(1);
for (int f = 0; f < icount; ++f) {
writer.writeObject(r.getNormalFieldValue(f));
}
int offset = bufferWriter.getCount();
for (int f = icount; f < vcount; ++f) {
bufferWriter.writeObject(r.getNormalFieldValue(f));
}
offset = bufferWriter.getCount() - offset;//?õ???һ???ij?????
writer.writeInt(offset);
}
//?ύһ??
byte []bytes = bufferWriter.finish();
writer.writeInt(BLOCK_VALUE_START);
writer.writeInt(bytes.length);
long temp = writer.position();
posList2.add(temp);
writer.write(bytes);
blockCount++;
maxValues.add(r);
if (rest == 0) break;
}
table = cursor.fetch(MAX_LEAF_BLOCK_COUNT * FETCH_SIZE);
}
writer.writeInt(BLOCK_END);
} else {
table = cursor.fetchGroup(ifs, MAX_LEAF_BLOCK_COUNT * FETCH_SIZE, ctx);
if (table == null || table.length() == 0) {
MessageManager mm = EngineMessage.get();
throw new RQException("index" + mm.getMessage("function.invalidParam"));
}
int p = 1;
IArray mems = table.getMems();
int length = table.length();
while (table != null && length != 0) {
if (bufferWriter == null) {
writer.writeInt(BLOCK_START);
} else {
//?ύһ??
byte []bytes = bufferWriter.finish();
writer.writeInt(BLOCK_VALUE_START);
writer.writeInt(bytes.length);
long temp = writer.position();
posList2.add(temp);
writer.write(bytes);
//?¿?
writer.writeInt(BLOCK_START);
}
int count = 0;
//??д0????????д??ʵֵ
blockValueStartPos = writer.position();
posList1.add(blockValueStartPos);
writer.writeLong40(0);
bufferWriter = new RowBufferWriter(null);//дvalue??buffer
while (count < perCount) {
int len = getGroupNum(mems, p, icount);
recCount += len;
count += len;
r = (Record)mems.get(p);
writer.writeInt(len);
for (int f = 0; f < icount; ++f) {
writer.writeObject(r.getNormalFieldValue(f));
}
for (int i = 0; i < len; ++i) {
r = (Record)mems.get(i + p);
int offset = bufferWriter.getCount();
for (int f = icount; f < vcount; ++f) {
bufferWriter.writeObject(r.getNormalFieldValue(f));
}
offset = bufferWriter.getCount() - offset;//?õ???һ???ij?????
writer.writeInt(offset);
}
p += len;
if (p > length) {
table = cursor.fetchGroup(ifs, MAX_LEAF_BLOCK_COUNT * FETCH_SIZE, ctx);
if (table == null || table.length() == 0) break;
p = 1;
mems = table.getMems();
length = table.length();
}
}
blockCount++;
maxValues.add(r);
}
//?ύ???һ??
byte []bytes = bufferWriter.finish();
writer.writeInt(BLOCK_VALUE_START);
writer.writeInt(bytes.length);
long temp = writer.position();
posList2.add(temp);
writer.write(bytes);
writer.writeInt(BLOCK_END);
}
} catch (IOException e) {
if (indexFile != null) {
indexFile.delete();
}
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException ie){};
}
//??ȥдValuePos
os = indexFile.getRandomOutputStream(true);
writer = new RandomObjectWriter(os);
try {
int size = posList1.size();
for (int i = 0; i < size; i++) {
writer.position(posList1.get(i));
writer.writeLong40(posList2.get(i));
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException ie){};
}
//????recCount????????
this.recordCount = recCount + index1RecordCount;
long srcRecordCount = recordCount;//?ݴ?һ?£???Ϊ???ļ?ͷʱ?ᱻ???¸?ֵ
positions = new long[blockCount];
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
readHeader(reader);
if (isAppends) {
reader.seek(indexPos2);
} else {
indexPos = reader.position();;
}
reader.readInt();
for (int i = 0; i < blockCount; ++i) {
positions[i] = reader.position();
reader.readLong40();
while (true) {
int count = reader.readInt();
if (count == BLOCK_START)
break;
if (count == BLOCK_END)
break;
if (count == BLOCK_VALUE_START) {
reader.skipBytes(reader.readInt());
continue;
}
for (int f = 0; f < icount; ++f) {
reader.readObject();
}
for (int j = 0; j < count; ++j) {
reader.readObject();
}
}
}
itPos = reader.position();//interBlock??ʼλ??
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
os = indexFile.getRandomOutputStream(true);
writer = new RandomObjectWriter(os);
try {
writer.position(itPos);
for (int i = 0; i < blockCount; ++i) {
if (i % MAX_INTER_BLOCK_COUNT == 0) {
if (blockCount - i >= MAX_INTER_BLOCK_COUNT) {
writer.writeInt(MAX_INTER_BLOCK_COUNT);
} else {
writer.writeInt(blockCount - i);
}
}
for (int f = 0; f < icount; ++f) {
writer.writeObject(maxValues.get(i).getNormalFieldValue(f));
}
writer.writeLong(positions[i]);
}
//writer.writeLong64(itPos);
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException ie){};
}
//???rootMaxValues
int rootBlockCount = (blockCount/MAX_INTER_BLOCK_COUNT);
rootBlockCount += (blockCount % MAX_INTER_BLOCK_COUNT==0) ? 0 : 1;
rootMaxValues = new Record[rootBlockCount];
for (int i = 0; i < rootBlockCount - 1; i++) {
rootMaxValues[i] = maxValues.get((i+1)*MAX_INTER_BLOCK_COUNT-1);
}
rootMaxValues[rootBlockCount - 1] = maxValues.get(blockCount - 1);
//??? rootPositions
rootPositions = new long[rootBlockCount];
is = indexFile.getInputStream();
reader = new ObjectReader(is, BUFFER_SIZE);
try {
reader.seek(itPos);//??λ??internalBlock start
//reader.readInt();
for (int i = 0; i < blockCount; ++i) {
if (i % MAX_INTER_BLOCK_COUNT == 0){
rootPositions[i/MAX_INTER_BLOCK_COUNT] = reader.position();
reader.readInt();
}
for (int f = 0; f < icount; ++f) {
reader.readObject();
}
reader.readLong();
}
itPos = reader.position();
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
if (isAppends) {
rootItPos2 = itPos;
recordCount = srcRecordCount;
} else {
rootItPos = itPos;
rootItPos2 = 0;
recordCount = srcRecordCount;
index1RecordCount = srcRecordCount;//1????ļ?¼?????????˺??
index1EndPos = srcTable.getTotalRecordCount();//????1??ʱԴ??????????????DZ????????˺?ģ?Ҳ??????????
}
//дrootMaxValues rootPositions
os = indexFile.getRandomOutputStream(true);
writer = new RandomObjectWriter(os);
try {
writer.position(itPos);
writer.writeInt(rootBlockCount);
for (int i = 0; i < rootBlockCount; ++i) {
for (int f = 0; f < icount; ++f) {
writer.writeObject(rootMaxValues[i].getNormalFieldValue(f));
}
writer.writeLong(rootPositions[i]);
}
writer.writeLong64(blockCount);//internal????ܸ???
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException ie){};
}
if (!isAppends) {
indexPos2 = indexFile.size();
}
//write fileHead
os = indexFile.getRandomOutputStream(true);
writer = new RandomObjectWriter(os);
try {
writer.position(0);
updateHeader(writer);
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
writer.close();
} catch (IOException ie){};
}
}
private ArrayList sortCol(String []fields, String[] valueFields, Context ctx, Expression filter) {
CTableCursor srcCursor = new CTableCursor(srcTable, fields, valueFields, ctx, filter);
try {
int icount = fields.length;
DataStruct ds = srcTable.getDataStruct();
ifields = new String[icount];
boolean isPrimaryTable = srcTable.parent == null;
String []keyNames = srcTable.getSortedColNames();
ArrayList list = new ArrayList();
if (keyNames != null) {
for (String name : keyNames) {
list.add(name);
}
}
for (int i = 0; i < icount; ++i) {
int id = ds.getFieldIndex(fields[i]);
if (id == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException(fields[i] + mm.getMessage("ds.fieldNotExist"));
}
if(!isPrimaryTable) {
if (list.contains(fields[i])) {
MessageManager mm = EngineMessage.get();
throw new RQException(fields[i] + mm.getMessage("ds.fieldNotExist"));
}
}
ifields[i] = fields[i];
}
if (valueFields != null) {
for (String f : valueFields) {
int id = ds.getFieldIndex(f);
if (id == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException(f + mm.getMessage("ds.fieldNotExist"));
}
}
vfields = valueFields;
}
//??????½????ı?
if (srcTable.getActualRecordCount() == 0) {
return null;
}
//????Ƿ??Ƕ?????????????
keyNames = srcTable.getAllSortedColNames();
if (srcTable.isSorted && keyNames != null && keyNames.length >= fields.length) {
boolean isKeyField = true;
for (int i = 0, len = fields.length; i < len; ++i) {
if (!fields[i].equals(keyNames[i])) {
isKeyField = false;
break;
}
}
if (isKeyField) {
if (index1EndPos > 0) {
srcCursor.seek(index1EndPos);
}
ArrayList cursorList = new ArrayList();
cursorList.add(srcCursor);
srcCursor = null;
return cursorList;
}
}
Runtime rt = Runtime.getRuntime();
int baseCount = 100000;//ÿ??ȡ??????????
boolean flag = false;//?Ƿ????????ʱ?ļ???С
ArrayList cursorList = new ArrayList();
Table table;
int []sortFields = new int[icount];
for (int i = 0; i < icount; ++i) {
sortFields[i] = i;
}
if (index1EndPos > 0) {
srcCursor.seek(index1EndPos);
}
while (true) {
table = (Table) srcCursor.get(baseCount);
if (table == null) break;
if (table.length() <= 0) break;
recordCount += table.length();
if (table.length() < baseCount)
break;
table.sortFields(sortFields);
FileObject tmp = FileObject.createTempFileObject();
tmp.exportSeries(table, "b", null);
BFileCursor bfc = new BFileCursor(tmp, null, "x", ctx);
cursorList.add(bfc);
table = null;
if (!flag && tmp.size() < TEMP_FILE_SIZE) {
baseCount = (int) (baseCount * (TEMP_FILE_SIZE / tmp.size()));
flag = true;
}
EnvUtil.runGC(rt);
}
//this.recordCount = recordCount + index1RecordCount;
int size = cursorList.size();
if (size > 1) {
int bufSize = Env.getMergeFileBufSize(size);
for (int i = 0; i < size; ++i) {
BFileCursor bfc = (BFileCursor)cursorList.get(i);
bfc.setFileBufferSize(bufSize);
}
}
if (table != null && table.length() > 0) {
table.sortFields(sortFields);
MemoryCursor mc = new MemoryCursor(table);
cursorList.add(mc);
}
return cursorList;
} finally {
if (srcCursor != null)
srcCursor.close();
}
}
private ArrayList sortRow(String []fields, String[] valueFields ,Context ctx, Expression filter) {
RTableCursor srcCursor = new RTableCursor(srcTable, fields, valueFields, ctx, filter);
try {
int icount = fields.length;
DataStruct ds = srcTable.getDataStruct();
ifields = new String[icount];
boolean isPrimaryTable = srcTable.parent == null;
String []keyNames = srcTable.groupTable.baseTable.getSortedColNames();
ArrayList list = new ArrayList();
for (String name : keyNames) {
list.add(name);
}
for (int i = 0; i < icount; ++i) {
int id = ds.getFieldIndex(fields[i]);
if (id == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException(fields[i] + mm.getMessage("ds.fieldNotExist"));
}
if(!isPrimaryTable) {
if (list.contains(fields[i])) {
MessageManager mm = EngineMessage.get();
throw new RQException(fields[i] + mm.getMessage("ds.fieldNotExist"));
}
}
ifields[i] = fields[i];
}
if (valueFields != null) {
for (String f : valueFields) {
int id = ds.getFieldIndex(f);
if (id == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException(f + mm.getMessage("ds.fieldNotExist"));
}
}
vfields = valueFields;
}
//??????½????ı?
if (srcTable.getActualRecordCount() == 0) {
return null;
}
//????Ƿ??Ƕ?????????????
keyNames = srcTable.getSortedColNames();
if (srcTable.isSorted && keyNames != null && keyNames.length >= fields.length) {
boolean isKeyField = true;
for (int i = 0, len = fields.length; i < len; ++i) {
if (!fields[i].equals(keyNames[i])) {
isKeyField = false;
break;
}
}
if (isKeyField) {
if (index1EndPos > 0) {
srcCursor.seek(index1EndPos);
}
ArrayList cursorList = new ArrayList();
cursorList.add(srcCursor);
srcCursor = null;
return cursorList;
}
}
Runtime rt = Runtime.getRuntime();
int baseCount = 100000;//ÿ??ȡ??????????
boolean flag = false;//?Ƿ????????ʱ?ļ???С
ArrayList cursorList = new ArrayList();
Table table;
int []sortFields = new int[icount];
for (int i = 0; i < icount; ++i) {
sortFields[i] = i;
}
if (index1EndPos > 0) {
srcCursor.seek(index1EndPos);
}
while (true) {
table = (Table) srcCursor.get(baseCount);
if (table == null) break;
if (table.length() <= 0) break;
recordCount += table.length();
if (table.length() < baseCount)
break;
table.sortFields(sortFields);
FileObject tmp = FileObject.createTempFileObject();
tmp.exportSeries(table, "b", null);
BFileCursor bfc = new BFileCursor(tmp, null, "x", ctx);
cursorList.add(bfc);
table = null;
if (!flag && tmp.size() < TEMP_FILE_SIZE) {
baseCount = (int) (baseCount * (TEMP_FILE_SIZE / tmp.size()));
flag = true;
}
EnvUtil.runGC(rt);
}
int size = cursorList.size();
if (size > 1) {
int bufSize = Env.getMergeFileBufSize(size);
for (int i = 0; i < size; ++i) {
BFileCursor bfc = (BFileCursor)cursorList.get(i);
bfc.setFileBufferSize(bufSize);
}
}
if (table.length() > 0) {
table.sortFields(sortFields);
MemoryCursor mc = new MemoryCursor(table);
cursorList.add(mc);
}
return cursorList;
} finally {
if (srcCursor != null)
srcCursor.close();
}
}
private static int binarySearch(Object[] objs, Object key) {
int low = 0;
int high = objs.length - 1;
while (low <= high) {
int mid = (low + high) >> 1;
int cmp = Variant.compare(objs[mid], key, true);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
if (low < objs.length) {
return low;
} else {
return -1;
}
}
private static int binarySearchArray(Object[][] objs, Object []keys, boolean isStart) {
int keyCount = keys.length;
int low = 0;
int high = objs.length - 1;
while (low <= high) {
int mid = (low + high) >> 1;
int cmp = Variant.compareArrays(objs[mid], keys, keyCount);
if (cmp < 0) {
low = mid + 1;
} else if (cmp > 0) {
high = mid - 1;
} else {
// ֻ?Բ????????ֶ???????ʱ???????ظ???
if (isStart) { // ????ʼλ??
for (int i = mid - 1; i >= 0; --i) {
if (Variant.compareArrays(objs[i], keys, keyCount) == 0) {
mid = i;
} else {
break;
}
}
} else { // ?ҽ???λ??
for (int i = mid + 1; i <= high; ++i) {
if (Variant.compareArrays(objs[i], keys, keyCount) == 0) {
mid = i;
} else {
break;
}
}
if (mid < objs.length - 1) mid++;
}
return mid; // key found
}
}
if (low < objs.length) {
return low;
} else {
return -1;
}
}
//????ֵ???ҿ?ź?λ?ã?????????????????
//key[] Ҫ???ҵ?ֵ
//icount ?ֶθ???
//isStart ?Ƿ????ҿ?ʼ
//pos[] ????ҵ???λ??
//index[] ????ҵ??Ŀ??
private void searchValue(Object[] key, int icount, boolean isStart, long[] pos, int[] index) {
//int rootBlockCount = rootBlockMaxVals.length;
int i = 0;
int j;
index[0] = -1;
pos[0] = -1;
index[1] = -1;
pos[1] = -1;
BlockInfo blockInfo = new BlockInfo();
while (true) {
if (icount == 1) {
i = binarySearch(rootBlockMaxVals, key[0]);
if (i < 0) {
break;
}
if (internalAllBlockPos == null) {
readInternalBlockInfo(indexFile, rootBlockPos[i], blockInfo);
} else {
readInternalBlockInfo(false, i, blockInfo);
}
j = binarySearch(blockInfo.internalBlockMaxVals, key[0]);
} else {
i = binarySearchArray((Object[][])rootBlockMaxVals, key, isStart);
if (i < 0) {
break;
}
if (internalAllBlockPos == null) {
readInternalBlockInfo(indexFile, rootBlockPos[i], blockInfo);
} else {
readInternalBlockInfo(false, i, blockInfo);
}
j = binarySearchArray((Object[][])blockInfo.internalBlockMaxVals, key, isStart);
}
if (j < 0) {
break;
}
index[0] = i * MAX_INTER_BLOCK_COUNT + j;
pos[0] = blockInfo.internalBlockPos[j];
break;
}
if (rootItPos2 == 0) {
return;
}
//rootBlockCount = rootBlockMaxVals2.length;
i = 0;
while (true) {
if (icount == 1) {
i = binarySearch(rootBlockMaxVals2, key[0]);
if (i < 0) {
break;
}
if (internalAllBlockPos2 == null) {
readInternalBlockInfo(indexFile, rootBlockPos2[i], blockInfo);
} else {
readInternalBlockInfo(true, i, blockInfo);
}
j = binarySearch(blockInfo.internalBlockMaxVals, key[0]);
} else {
i = binarySearchArray((Object[][])rootBlockMaxVals2, key, isStart);
if (i < 0) {
break;
}
if (internalAllBlockPos2 == null) {
readInternalBlockInfo(indexFile, rootBlockPos2[i], blockInfo);
} else {
readInternalBlockInfo(true, i, blockInfo);
}
j = binarySearchArray((Object[][])blockInfo.internalBlockMaxVals, key, isStart);
}
if (j < 0) {
break;
}
index[1] = i * MAX_INTER_BLOCK_COUNT + j;
pos[1] = blockInfo.internalBlockPos[j];
break;
}
}
private void readBlockInfo(FileObject fo) {
int rootBlockCount1 = 0;
int rootBlockCount2 = 0;
if ((rootBlockMaxVals != null)
&& (rootItPos2 == 0 || rootBlockMaxVals2 != null)) {
return;
}
InputStream is = fo.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
readHeader(reader);
int icount = ifields.length;
if (rootBlockMaxVals == null) {
reader.seek(rootItPos);
rootBlockCount1 = reader.readInt(); // ????????
Object []maxValues;
long []positions = new long[rootBlockCount1];
if (icount == 1) {
maxValues = new Object[rootBlockCount1];
for (int i = 0; i < rootBlockCount1; ++i) {
maxValues[i] = reader.readObject();
positions[i] = reader.readLong();
}
} else {
maxValues = new Object[rootBlockCount1][];
for (int i = 0; i < rootBlockCount1; ++i) {
Object []vals = new Object[icount];
for (int f = 0; f < icount; ++f) {
vals[f] = reader.readObject();
}
maxValues[i] = vals;
positions[i] = reader.readLong();
}
}
this.rootBlockMaxVals = maxValues;
this.rootBlockPos = positions;
this.internalBlockCount = reader.readLong64();
}
if (rootItPos2 != 0 && rootBlockMaxVals2 == null) {
reader.seek(rootItPos2);
rootBlockCount2 = reader.readInt(); // ????????
Object []maxValues;
long []positions = new long[rootBlockCount2];
if (icount == 1) {
maxValues = new Object[rootBlockCount2];
for (int i = 0; i < rootBlockCount2; ++i) {
maxValues[i] = reader.readObject();
positions[i] = reader.readLong();
}
} else {
maxValues = new Object[rootBlockCount2][];
for (int i = 0; i < rootBlockCount2; ++i) {
Object []vals = new Object[icount];
for (int f = 0; f < icount; ++f) {
vals[f] = reader.readObject();
}
maxValues[i] = vals;
positions[i] = reader.readLong();
}
}
this.rootBlockMaxVals2 = maxValues;
this.rootBlockPos2 = positions;
this.internalBlockCount2 = reader.readLong64();
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
}
/**
* ??ȡһ???м????Ϣ
* @param fo
* @param pos
* @param blockInfo ???
*/
private void readInternalBlockInfo(FileObject fo, long pos, BlockInfo blockInfo) {
int interBlockCount;
InputStream is = fo.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
int icount = ifields.length;
reader.seek(pos);
interBlockCount = reader.readInt(); // ????????
Object []maxValues;
long []positions = new long[interBlockCount];
if (icount == 1) {
maxValues = new Object[interBlockCount];
for (int i = 0; i < interBlockCount; ++i) {
maxValues[i] = reader.readObject();
positions[i] = reader.readLong();
}
} else {
maxValues = new Object[interBlockCount][];
for (int i = 0; i < interBlockCount; ++i) {
Object []vals = new Object[icount];
for (int f = 0; f < icount; ++f) {
vals[f] = reader.readObject();
}
maxValues[i] = vals;
positions[i] = reader.readLong();
}
}
blockInfo.internalBlockMaxVals = maxValues;
blockInfo.internalBlockPos = positions;
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
}
// ???ؼ?¼??
public long count() {
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
readHeader(reader);
return recordCount;
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
}
public ICursor select(Object []startVals, Object []endVals,
String []fields, String opt, Context ctx) {
readBlockInfo(indexFile);
boolean le = opt == null || opt.indexOf('l') == -1;
boolean re = opt == null || opt.indexOf('r') == -1;
int icount = ifields.length;
Object []srcPos = null;
Object []srcPos2 = null;
if (startVals == null) {
if (endVals.length > ifields.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
int end[] = new int[2];
long endPos[] = new long[2];
searchValue(endVals, icount, false, endPos, end);
if (end[0] < 0 && end[1] < 0) {
return srcTable.cursor(fields);
}
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (end[0] >= 0) {
if (icount == 1) {
srcPos = readPos_s(reader, endVals[0], end[0], re ? LE : LT, indexPos + 5, 0);
} else {
srcPos = readPos_m(reader, endVals, end[0], re ? LE : LT, indexPos + 5, 0);
}
}
if (rootItPos2 != 0) {
if (end[1] >= 0) {
if (icount == 1) {
srcPos2 = readPos_s(reader, endVals[0], end[1], re ? LE : LT, indexPos2 + 5, 0);
} else {
srcPos2 = readPos_m(reader, endVals, end[1], re ? LE : LT, indexPos2 + 5, 0);
}
}
}
if (srcPos == null) {
srcPos = srcPos2;
} else if (srcPos2 != null) {
srcPos = concat(srcPos, srcPos2);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
} else if (endVals == null) {
if (startVals.length > ifields.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
int start[] = new int[2];
long startPos[] = new long[2];
searchValue(startVals, icount, true, startPos, start);
if (start[0] < 0 && start[1] < 0) return null;
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (start[0] >= 0) {
if (icount == 1) {
srcPos = readPos_s(reader, startVals[0], start[0], le ? GE : GT, 0, startPos[0]);
} else {
srcPos = readPos_m(reader, startVals, start[0], le ? GE : GT, 0, startPos[0]);
}
}
if (rootItPos2 != 0) {
if (start[1] >= 0) {
if (icount == 1) {
srcPos2 = readPos_s(reader, startVals[0], start[1], le ? GE : GT, 0, startPos[1]);
} else {
srcPos2 = readPos_m(reader, startVals, start[1], le ? GE : GT, 0, startPos[1]);
}
}
}
if (srcPos == null) {
srcPos = srcPos2;
} else if (srcPos2 != null) {
srcPos = concat(srcPos, srcPos2);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
} else {
if (startVals.length > ifields.length || endVals.length > ifields.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
if (startVals.length != endVals.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("psort" + mm.getMessage("function.paramCountNotMatch"));
}
int cmp = Variant.compareArrays(startVals, endVals);
if (cmp > 0) {
return null;
} else if (cmp == 0 && (!le || !re)) {
return null;
}
int start[] = new int[2];
long startPos[] = new long[2];
int end[] = new int[2];
long endPos[] = new long[2];
searchValue(startVals, icount, true, startPos, start);
if (start[0] < 0 && start[1] < 0) return null;
searchValue(endVals, icount, false, endPos, end);
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (start[0] >= 0) {
if (end[0] < 0) {
if (icount == 1) {
srcPos = readPos_s(reader, startVals[0], start[0], le ? GE : GT, 0, startPos[0]);
} else {
srcPos = readPos_m(reader, startVals, start[0], le ? GE : GT, 0, startPos[0]);
}
} else {
if (icount == 1) {
srcPos = readPos_s(reader, startVals[0], start[0], le, endVals[0], end[0], re, startPos[0]);
} else {
srcPos = readPos_m(reader, startVals, start[0], le, endVals, end[0], re, startPos[0]);
}
}
}
if (rootItPos2 != 0) {
if (start[1] >= 0) {
if (end[1] < 0) {
if (icount == 1) {
srcPos2 = readPos_s(reader, startVals[0], start[1], le ? GE : GT, 0, startPos[1]);
} else {
srcPos2 = readPos_m(reader, startVals, start[1], le ? GE : GT, 0, startPos[1]);
}
} else {
if (icount == 1) {
srcPos2 = readPos_s(reader, startVals[0], start[1], le, endVals[0], end[1], re, startPos[1]);
} else {
srcPos2 = readPos_m(reader, startVals, start[1], le, endVals, end[1], re, startPos[1]);
}
}
}
}
if (srcPos == null) {
srcPos = srcPos2;
} else if (srcPos2 != null) {
srcPos = concat(srcPos, srcPos2);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
}
if (srcPos == null) return null;
return makeCursor(fields, srcPos);
}
public ICursor select(Object []vals, String []fields, String opt, Context ctx) {
readBlockInfo(indexFile);
int icount = ifields.length;
int n[] = new int[2];
long pos[] = new long[2];
searchValue(vals, icount, true, pos, n);
if (n[0] < 0 && n[1] < 0) return null;
Object []srcPos = null;
Object []srcPos2 = null;
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (n[0] >= 0) {
if (icount == 1) {
srcPos = readPos_s(reader, vals[0], n[0], EQ, 0, pos[0]);
} else {
srcPos = readPos_m(reader, vals, n[0], EQ, 0, pos[0]);
}
}
if (rootItPos2 != 0) {
if (n[1] >= 0) {
if (icount == 1) {
srcPos2 = readPos_s(reader, vals[0], n[1], EQ, 0, pos[1]);
} else {
srcPos2 = readPos_m(reader, vals, n[1], EQ, 0, pos[1]);
}
}
}
if (srcPos == null) {
srcPos = srcPos2;
} else if (srcPos2 != null) {
srcPos = concat(srcPos, srcPos2);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
if (srcPos == null) return null;
return makeCursor(fields, srcPos);
}
public ICursor select(Sequence vals, String []fields, String opt, Context ctx) {
if (vals == null || vals.length() == 0) return null;
readBlockInfo(indexFile);
Object []srcPos;
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (ifields.length == 1) {
srcPos = readPos_s(reader, vals);
} else {
srcPos = readPos_m(reader, vals);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
if (srcPos == null) return null;
return makeCursor(fields, srcPos);
}
public ICursor select(Expression exp, String []fields, String opt, Context ctx) {
readBlockInfo(indexFile);
int icount = ifields.length;
if (icount == 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("Expression.unknownExpression") + exp.toString());
}
//????contain????ʽ
Node home = exp.getHome();
if (home instanceof DotOperator) {
Node left = home.getLeft();
Node right = home.getRight();
if (!(right instanceof Contain)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
Sequence series;
Object obj = left.calculate(ctx);
if (obj instanceof Sequence) {
series = (Sequence) obj;
} else {
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(" ", "");
String[] split = str.split(",");
if (series == null || 0 != Variant.compareArrays(ifields, split, split.length)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
series.sort("o");
return select(series, fields, opt, ctx);
}
//????like(F,"xxx*")????ʽ
if (home instanceof Like) {
if (((Like) home).getParam().getSubSize() != 2) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
IParam sub1 = ((Like) home).getParam().getSub(0);
IParam sub2 = ((Like) home).getParam().getSub(1);
String f = (String) sub1.getLeafExpression().getIdentifierName();
if (!f.equals(ifields[0])) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
String fmtExp = (String) sub2.getLeafExpression().calculate(ctx);
int idx = fmtExp.indexOf("*");
if (idx > 0) {
fmtExp = fmtExp.substring(0, idx);
return select(fields, new String[]{fmtExp}, exp, ctx);
}
}
FieldFilter []filters = new FieldFilter[icount];
if (getFieldFilters(exp.getHome(), filters, ctx)) {
int last = icount - 1;
for (; last >= 0; --last) {
if (filters[last] != null) break;
}
// ???????Ķ?????ȱȽ???????Ż???[a,b...v1]:[a,b...v2]
boolean canOpt = true;
for (int i = 0; i < last; ++i) {
if (filters[i] == null || filters[i].startSign != EQ) {
canOpt = false;
break;
}
}
if (canOpt) {
if (filters[last].startSign == EQ) {
Object []vals = new Object[last + 1];
for (int i = 0; i <= last; ++i) {
vals[i] = filters[i].startVal;
}
if (icount == last + 1) {
//??????????ֶεĵ???
Sequence seq = new Sequence();
seq.addAll(vals);
if (icount == 1) {
return select(seq, fields, opt, ctx);
}
Sequence series = new Sequence();
series.add(seq);
return select(series, fields, opt, ctx);
}
return select(vals, fields, opt, ctx);
} else if (filters[last].startSign != NULL && filters[last].endSign != NULL) {
Object []startVals = new Object[last + 1];
Object []endVals = new Object[last + 1];
for (int i = 0; i <= last; ++i) {
startVals[i] = filters[i].startVal;
endVals[i] = filters[i].startVal;
}
endVals[last] = filters[last].endVal;
if (opt == null) opt = "";
if (filters[last].startSign == GT) opt += "l";
if (filters[last].endSign == LT) opt += "r";
return select(startVals, endVals, fields, opt, ctx);
}
}
}
//?????????true??????ȡȫ??
if (exp.getHome() instanceof Constant
&& Variant.isTrue(exp.calculate(ctx))
&& srcTable.getModifyRecords() == null) {
ICursor cs = new IndexFCursor(this, indexPos + 5);
if (rootItPos2 != 0) {
ICursor cs2 = new IndexFCursor(this, indexPos2 + 5);
ICursor []cursors = new ICursor[]{cs, cs2};
Expression []exps = new Expression[icount];
for (int i = 0; i < ifields.length; ++i) {
exps[i] = new Expression(ctx, "#" + (i + 1));
}
cs = new MergesCursor(cursors, exps, ctx);
}
if (fields != null) {
Expression []exps = new Expression[fields.length];
for (int i = 0; i < fields.length; ++i) {
exps[i] = new Expression(ctx, "#" + (i + 1));
}
New newOp = new New(exps, fields, null);
cs.addOperation(newOp, ctx);
}
return cs;
}
Sequence vals = new Sequence(icount); // ǰ????????жϵ??ֶε?ֵ
FieldFilter ff = null; // ??һ??????????жϵ??ֶε???Ϣ
for (int i = 0; i < icount; ++i) {
FieldFilter filter = new FieldFilter();
getFieldFilter(i, exp.getHome(), filter, ctx);
if (filter.startSign == EQ) {
vals.add(filter.startVal);
} else {
ff = filter;
break;
}
}
int start[] = new int[2];
long startPos[] = new long[2];
int end[] = new int[2];
long endPos[] = new long[2];
startPos[0] = indexPos + 5;
startPos[1] = indexPos2 + 5;
start[0] = start[1] = 0;
end[0] = (int) (this.internalBlockCount - 1);
end[1] = (int) (this.internalBlockCount2- 1);
int eqCount = vals.length();
if (eqCount == 0) {
if (ff != null && ff.startSign != NULL) {
Object []keys = new Object[]{ff.startVal};
searchValue(keys, icount, true, startPos, start);
if (start[0] < 0 && start[1] < 0) return null;
}
if (ff != null && ff.endSign != NULL) {
Object []keys = new Object[]{ff.endVal};
searchValue(keys, icount, false, endPos, end);
if (end[0] < 0) end[0] = (int) (this.internalBlockCount - 1);
if (end[1] < 0) end[1] = (int) (this.internalBlockCount2 - 1);
}
} else {
if (ff == null || ff.startSign == NULL) {
Object []keys = vals.toArray();
searchValue(keys, icount, true, startPos, start);
} else {
Object []keys = new Object[eqCount + 1];
vals.toArray(keys);
keys[eqCount] = ff.startVal;
searchValue(keys, eqCount + 1, true, startPos, start);
}
if (start[0] < 0 && start[1] < 0) return null;
if (ff == null || ff.endSign == NULL) {
if (icount == 1) {
end[0] = start[0];
end[1] = start[1];
} else {
Object []keys = vals.toArray();
searchValue(keys, icount, false, endPos, end);
}
} else {
Object []keys = new Object[eqCount + 1];
vals.toArray(keys);
keys[eqCount] = ff.endVal;
searchValue(keys, icount, false, endPos, end);
}
if (end[0] < 0) end[0] = (int) (this.internalBlockCount - 1);
if (end[1] < 0) end[1] = (int) (this.internalBlockCount2 - 1);
}
Object []srcPos = null;
Object []srcPos2 = null;
InputStream is = indexFile.getInputStream();
ObjectReader reader = new ObjectReader(is, BUFFER_SIZE);
try {
if (opt != null && opt.indexOf('s') != -1) {
ICursor cs1 = null;
ICursor cs2 = null;
if (start[0] >= 0) {
cs1 = readPos(fields, reader, exp, ctx, start[0], end[0], startPos[0]);
}
if (rootItPos2 != 0) {
if (start[1] >= 0) {
cs2 = readPos(fields, reader, exp, ctx, start[1], end[1], startPos[1]);
}
}
if (cs1 == null) {
return cs2;
} else if (cs2 == null) {
return cs1;
} else {
ICursor []cursors = new ICursor[]{cs1, cs2};
Expression []exps = new Expression[icount];
for (int i = 0; i < ifields.length; ++i) {
exps[i] = new Expression(ctx, "#" + (i + 1));
}
return new MergesCursor(cursors, exps, ctx);
}
}
if (start[0] >= 0) {
srcPos = readPos(reader, exp, ctx, start[0], end[0], startPos[0]);
}
if (rootItPos2 != 0) {
if (start[1] >= 0) {
srcPos2 = readPos(reader, exp, ctx, start[1], end[1], startPos[1]);
}
}
if (srcPos == null) {
srcPos = srcPos2;
} else if (srcPos2 != null) {
srcPos = concat(srcPos, srcPos2);
}
} catch (IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
reader.close();
} catch (IOException ie){};
}
if (srcPos == null) return null;
return makeCursor(fields, srcPos);
}
private boolean equalField(int fieldIndex, Node node) {
if (node instanceof UnknownSymbol) {
if (ifields[fieldIndex].equals(((UnknownSymbol)node).getName())) {
return true;
}
} else if (node instanceof FieldId) {
return ((FieldId)node).getFieldIndex() == fieldIndex;
}
return false;
}
private boolean getFieldFilters(Node home, FieldFilter []filters, Context ctx) {
if (!(home instanceof Operator)) return false;
Node left = home.getLeft();
Node right = home.getRight();
if (home instanceof And) {
if (!getFieldFilters(left, filters, ctx)) return false;
return getFieldFilters(right, filters, ctx);
} else if (home instanceof Equals) { // ==
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else {
return false;
}
filters[i].startSign = EQ;
filters[i].startVal = right.calculate(ctx);
return true;
} else if (equalField(i, right)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else {
return false;
}
filters[i].startSign = EQ;
filters[i].startVal = left.calculate(ctx);
return true;
}
}
} else if (home instanceof NotSmaller) { // >=
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].startSign != NULL) {
return false;
}
filters[i].startSign = GE;
filters[i].startVal = right.calculate(ctx);
return true;
} else if (equalField(i, right)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].endSign != NULL) {
return false;
}
filters[i].endSign = LE;
filters[i].endVal = left.calculate(ctx);
return true;
}
}
} else if (home instanceof Greater) { // >
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].startSign != NULL) {
return false;
}
filters[i].startSign = GT;
filters[i].startVal = right.calculate(ctx);
return true;
} else if (equalField(i, right)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].endSign != NULL) {
return false;
}
filters[i].endSign = LT;
filters[i].endVal = left.calculate(ctx);
return true;
}
}
} else if (home instanceof NotGreater) { // <=
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].endSign != NULL) {
return false;
}
filters[i].endSign = LE;
filters[i].endVal = right.calculate(ctx);
return true;
} else if (equalField(i, right)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].startSign != NULL) {
return false;
}
filters[i].startSign = GE;
filters[i].startVal = left.calculate(ctx);
return true;
}
}
} else if (home instanceof Smaller) { // <
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].endSign != NULL) {
return false;
}
filters[i].endSign = LT;
filters[i].endVal = right.calculate(ctx);
return true;
} else if (equalField(i, right)) {
if (filters[i] == null) {
filters[i] = new FieldFilter();
} else if (filters[i].startSign != NULL) {
return false;
}
filters[i].startSign = GT;
filters[i].startVal = left.calculate(ctx);
return true;
}
}
}
return false;
}
// ?ҳ??????ֶε?????
private void getFieldFilter(int fieldIndex, Node home, FieldFilter filter, Context ctx) {
if (!(home instanceof Operator)) return;
Node left = home.getLeft();
Node right = home.getRight();
if (home instanceof And) {
getFieldFilter(fieldIndex, left, filter, ctx);
getFieldFilter(fieldIndex, right, filter, ctx);
} else if (home instanceof Equals) { // ==
if (equalField(fieldIndex, left)) {
filter.startSign = EQ;
filter.startVal = right.calculate(ctx);
} else if (equalField(fieldIndex, right)) {
filter.startSign = EQ;
filter.startVal = left.calculate(ctx);
}
} else if (home instanceof NotSmaller) { // >=
if (equalField(fieldIndex, left)) {
filter.startSign = GE;
filter.startVal = right.calculate(ctx);
} else if (equalField(fieldIndex, right)) {
filter.endSign = LE;
filter.endVal = left.calculate(ctx);
}
} else if (home instanceof Greater) { // >
if (equalField(fieldIndex, left)) {
filter.startSign = GT;
filter.startVal = right.calculate(ctx);
} else if (equalField(fieldIndex, right)) {
filter.endSign = LT;
filter.endVal = left.calculate(ctx);
}
} else if (home instanceof NotGreater) { // <=
if (equalField(fieldIndex, left)) {
filter.endSign = LE;
filter.endVal = right.calculate(ctx);
} else if (equalField(fieldIndex, right)) {
filter.startSign = GE;
filter.startVal = left.calculate(ctx);
}
} else if (home instanceof Smaller) { // <
if (equalField(fieldIndex, left)) {
filter.endSign = LT;
filter.endVal = right.calculate(ctx);
} else if (equalField(fieldIndex, right)) {
filter.startSign = GT;
filter.startVal = left.calculate(ctx);
}
} // ????or???????????
}
private Object [] readPos(ObjectReader reader, Expression exp, Context ctx,
int start, int end, long startPos) throws IOException {
int icount = ifields.length;
reader.seek(startPos);
ArrayList posList = new ArrayList(16);
ArrayList
© 2015 - 2024 Weber Informatics LLC | Privacy Policy