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.MemoryTableIndex Maven / Gradle / Ivy
Go to download
SPL(Structured Process Language) A programming language specially for structured data computing.
package com.scudata.dw;
import java.util.ArrayList;
import java.util.HashMap;
import com.scudata.array.IArray;
import com.scudata.array.IntArray;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.ComputeStack;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.HashIndexTable;
import com.scudata.dm.IndexTable;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MemoryCursor;
import com.scudata.dm.op.New;
import com.scudata.dm.op.Select;
import com.scudata.expression.Expression;
import com.scudata.expression.FieldId;
import com.scudata.expression.IParam;
import com.scudata.expression.Node;
import com.scudata.expression.Operator;
import com.scudata.expression.UnknownSymbol;
import com.scudata.expression.fn.string.Like;
import com.scudata.expression.mfn.sequence.Contain;
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.Or;
import com.scudata.expression.operator.Smaller;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;
/**
* ?ڱ???????
* @author LW
*
*/
public class MemoryTableIndex {
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 LIMIT = 1000000;//??Ƶ?????????????????ֵ??????
public static final int TEMP_FILE_SIZE = 100 * 1024 * 1024;//????ʱ?Ļ????ļ???С
private static final int MIN_HASH_SIZE = 4096;
public static final int TYPE_SORT = 0;
public static final int TYPE_HASH = 1;
public static final int TYPE_FULLTEXT = 2;
private static final String SORT_FIELD_NAME = "SORT_FIELD_NAME";
private Table srcTable;
private String name;// ????????????
private String[] ifields;// ?????ֶ?
private int type;
private int avgNums;//ƽ??ÿ??key?ļ?¼??
private Table indexData;// ??????????
private IntArray[] recordNums;// ???????????????Ӧ?ļ?¼??
private IndexTable indexTable;//???????????ڵ?ֵ???ң?
public MemoryTableIndex(String name, Table srcTable, String[] fields, Expression filter,
int capacity, int type, Context ctx) {
this.name = name;
if (filter != null) {
this.srcTable = ((Sequence)srcTable.select(filter, null, ctx)).derive(null);
} else {
this.srcTable = srcTable;
}
if (type == TYPE_SORT) {
if (fields.length == 1) {
createSortIndex(fields[0], ctx);
} else {
createSortIndex(fields, ctx);
}
} else if (type == TYPE_HASH) {
createHashIndex(fields, capacity, ctx);
} else {
createFullTextIndex(fields[0], capacity, ctx);
}
if (avgNums == 0) avgNums = 8;
}
public String[] getIfields() {
return ifields;
}
public String getName() {
return name;
}
public boolean getByName(String name) {
if (this.name.equals(name)) {
return true;
}
return false;
}
private class FieldFilter {
private Object startVal;
private Object endVal;
private int startSign = NULL;
private int endSign = NULL;
}
private void createHashIndex(String[] fields, int capacity, Context ctx) {
type = TYPE_HASH;
int len = srcTable.length();
if (capacity == 0) {
capacity = len / 2;
}
if (capacity < MIN_HASH_SIZE) {
capacity = MIN_HASH_SIZE;
}
if (capacity > len) {
capacity = len;
}
int flen = fields.length;
DataStruct ds = srcTable.dataStruct();
int[] findex = new int[flen];
for (int i = 0; i < flen; i++) {
findex[i] = ds.getFieldIndex(fields[i]);
}
if (flen == 1) {
HashIndexTable it = new HashIndexTable(capacity, "m");
it.create_i(srcTable, findex[0]);
this.indexTable = it;
} else {
this.indexTable = srcTable.newIndexTable(findex, capacity, "mU");
}
this.ifields = fields;
this.avgNums = avgNums / len;
}
private void createSortIndex(String field, Context ctx) {
type = TYPE_SORT;
Expression exp = new Expression(field);
Expression[] exps = new Expression[] {exp, new Expression("#")};
String[] names = new String[] {field, SORT_FIELD_NAME};
Sequence table = srcTable.newTable(names, exps, null, ctx);
table = table.sort(exp, null, "o", ctx);
table = table.group(exp, "o", ctx);
int len = table.length();
names = new String[] {field};
Table indexData = new Table(names, len);
IntArray[] recordNums = new IntArray[len + 1];
int avgNums = 0;
for (int i = 1; i <= len; i++) {
Sequence seq = (Sequence) table.getMem(i);
BaseRecord rec = (BaseRecord) seq.getMem(1);
int size = seq.length();
IntArray recNum = new IntArray(size);
for (int j = 1; j <= size; j++) {
BaseRecord record = (BaseRecord) seq.getMem(j);
Integer value = (Integer) record.getNormalFieldValue(1);
recNum.pushInt(value);
}
Object[] objs = new Object[] {rec.getNormalFieldValue(0)};
indexData.newLast(objs);
recordNums[i] = recNum;
avgNums += recNum.size();
}
indexData.dataStruct().setPrimary(names);
indexData.createIndexTable(len, "b");
this.indexData = indexData;
this.indexTable = indexData.getIndexTable();
this.recordNums = recordNums;
this.ifields = names;
this.avgNums = avgNums / len;
}
private void createSortIndex(String[] fields, Context ctx) {
type = TYPE_SORT;
int flen = fields.length;
Expression[] exp = new Expression[flen];
Expression[] exps = new Expression[flen + 1];
String[] names = new String[flen + 1];
String[] names2 = new String[flen];
for (int i = 0; i < flen; i++) {
exp[i] = exps[i] = new Expression(fields[i]);
names[i] = names2[i] = fields[i];
}
exps[flen] = new Expression("#");
names[flen] = SORT_FIELD_NAME;
Sequence table = srcTable.newTable(names, exps, null, ctx);
table = table.sort(exp, null, "o", ctx);
table = table.group(exp, "o", ctx);
int len = table.length();
int avgNums = 0;
Table indexData = new Table(names2, len);
IntArray[] recordNums = new IntArray[len + 1];
for (int i = 1; i <= len; i++) {
Sequence seq = (Sequence) table.getMem(i);
BaseRecord rec = (BaseRecord) seq.getMem(1);
int size = seq.length();
IntArray recNum = new IntArray(size);
for (int j = 1; j <= size; j++) {
BaseRecord record = (BaseRecord) seq.getMem(j);
Integer value = (Integer) record.getNormalFieldValue(flen);
recNum.pushInt(value);
}
Object[] objs = new Object[flen];
for (int f = 0; f < flen; f++) {
objs[f] = rec.getNormalFieldValue(f);
}
indexData.newLast(objs);
recordNums[i] = recNum;
avgNums += recNum.size();
}
indexData.dataStruct().setPrimary(names2);
indexData.createIndexTable(len, "b");
this.indexData = indexData;
this.indexTable = indexData.getIndexTable();
this.recordNums = recordNums;
this.ifields = names2;
this.avgNums = avgNums / len;
}
private void createFullTextIndex(String field, int capacity, Context ctx) {
type = TYPE_FULLTEXT;
Expression exp = new Expression(field);
Expression[] exps = new Expression[] {exp, new Expression("#")};
String[] names = new String[] {field, SORT_FIELD_NAME};
Sequence table = srcTable.newTable(names, exps, null, ctx);
table = fullTextSort(table, field);//table.sort(exp, null, "o", ctx);
table = table.group(exp, "o", ctx);
int len = table.length();
names = new String[] {field};
Table indexData = new Table(names, len);
IntArray[] recordNums = new IntArray[len + 1];
for (int i = 1; i <= len; i++) {
Sequence seq = (Sequence) table.getMem(i);
BaseRecord rec = (BaseRecord) seq.getMem(1);
int size = seq.length();
IntArray recNum = new IntArray(size);
for (int j = 1; j <= size; j++) {
BaseRecord record = (BaseRecord) seq.getMem(j);
Integer value = (Integer) record.getNormalFieldValue(1);
recNum.pushInt(value);
}
Object[] objs = new Object[] {rec.getNormalFieldValue(0)};
indexData.newLast(objs);
recordNums[i] = recNum;
}
table = null;
indexData.dataStruct().setPrimary(names);
indexData.createIndexTable(len, "b");
this.indexData = indexData;
this.indexTable = indexData.getIndexTable();
this.recordNums = recordNums;
this.ifields = names;
this.avgNums = 8;
}
/**
* ????ַ?key???ֵĴ???
* @param strCounters
* @param key
* @return
*/
private boolean checkStringCount(HashMap strCounters, String key) {
if (strCounters.containsKey(key)) {
Long cnt = strCounters.get(key) + 1;
if (cnt >= LIMIT) {
return true;
}
strCounters.put(key, cnt);
} else {
strCounters.put(key, (long) 1);
}
return false;
}
private boolean checkAlpha(char word) {
if (word >= '0' && word <= 'z') {
return true;
}
return false;
}
private Sequence fullTextSort(Sequence indexData, String field) {
DataStruct ds = indexData.dataStruct();
//check field
int id = ds.getFieldIndex(field);
if (id == -1) {
MessageManager mm = EngineMessage.get();
throw new RQException(field + mm.getMessage("ds.fieldNotExist"));
}
HashMap strCounters = new HashMap();//??¼ÿ???ַ????ֵĴ???
int fieldsCount = ds.getFieldCount();
ArrayList list = new ArrayList();
Sequence table;
Table subTable;
table = indexData;
if (table.length() <= 0) return indexData;
ds = table.dataStruct();
subTable = new Table(ds);
IArray mems = table.getMems();
int length = table.length();
for (int i = 1; i <= length; i++) {
Record r = (Record) mems.get(i);
Object []objs = r.getFieldValues();
if (objs[0] == null) {
continue;
}
if (!(objs[0] instanceof String)) {
MessageManager mm = EngineMessage.get();
throw new RQException("index" + mm.getMessage("function.paramTypeError"));
}
String ifield = (String) objs[0];
list.clear();//?????ж??ظ????ַ???????"??????ʿ"???ظ???"??"?ֲ??ܱ??ظ?????
int strLen = ifield.length();
for (int j = 0; j < strLen; j++) {
char ch1 = ifield.charAt(j);
if (ch1 == ' ') {
continue;//?ո?
}
if (checkAlpha(ch1)) {
//Ӣ??Ҫ????ȡ3????4????ĸ
if (j + 2 < strLen) {
char ch2 = ifield.charAt(j + 1);
char ch3 = ifield.charAt(j + 2);
if (checkAlpha(ch2) && checkAlpha(ch3)) {
Object []vals = new Object[fieldsCount];
for (int f = 1; f < fieldsCount; f++) {
vals[f] = objs[f];
}
String str3 = new String("" + ch1 + ch2 + ch3);
if (!list.contains(str3) && !checkStringCount(strCounters, str3)) {
vals[0] = str3;
subTable.newLast(vals);
list.add(str3);
}
if (j + 3 < strLen) {
char ch4 = ifield.charAt(j + 3);
if (checkAlpha(ch4)) {
String str4 = new String(str3 + ch4);
if (!list.contains(str4)) {
vals = new Object[fieldsCount];
for (int f = 1; f < fieldsCount; f++) {
vals[f] = objs[f];
}
vals[0] = str4;
subTable.newLast(vals);
list.add(str4);
}
}
}
}
}
} else if (ch1 > 255) {
String str = new String("" + ch1);
if (list.contains(str)) {
continue;//?Ѿ?????
}
//??????????
if (checkStringCount(strCounters, str)) {
continue;
}
Object []vals = new Object[fieldsCount];
for (int f = 1; f < fieldsCount; f++) {
vals[f] = objs[f];
}
vals[0] = str;
subTable.newLast(vals);
list.add(str);
}
}
}
if (subTable != null && subTable.length() != 0) {
subTable.sortFields(new int[] {0});
}
return subTable;
}
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 boolean getFieldFilters(Node home, ArrayList objs, Context ctx) {
if (!(home instanceof Operator)) return false;
Node left = home.getLeft();
Node right = home.getRight();
if (home instanceof Or) {
if (!getFieldFilters(left, objs, ctx)) return false;
return getFieldFilters(right, objs, ctx);
} else if (home instanceof Equals) { // ==
for (int i = 0, icount = ifields.length; i < icount; ++i) {
if (equalField(i, left)) {
objs.add(right.calculate(ctx));
return true;
} else if (equalField(i, right)) {
objs.add(left.calculate(ctx));
return true;
}
}
}
return false;
}
/**
* ?ҳ??????ֶε?????
* @param fieldIndex
* @param home
* @param filter
* @param ctx
*/
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 int binarySearch(Object key) {
IArray mems = indexData.getMems();
int len = mems.size();
int low = 1;
int high = len;
while (low <= high) {
int mid = (low + high) >> 1;
BaseRecord r = (BaseRecord)mems.get(mid);
Object obj = r.getNormalFieldValue(0);
int cmp = Variant.compare(obj, key, true);
if (cmp < 0)
low = mid + 1;
else if (cmp > 0)
high = mid - 1;
else
return mid; // key found
}
if (low < len + 1) {
return low;
} else {
return -1;
}
}
private int binarySearchArray(Object []keys, boolean isStart) {
IArray mems = indexData.getMems();
int len = mems.size();
int keyCount = keys.length;
Object[] vals = new Object[keyCount];
int low = 1;
int high = len;
while (low <= high) {
int mid = (low + high) >> 1;
BaseRecord r = (BaseRecord)mems.get(mid);
for (int f = 0; f < keyCount; ++f) {
vals[f] = r.getNormalFieldValue(f);
}
int cmp = Variant.compareArrays(vals, 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) {
r = (BaseRecord)mems.get(i);
for (int f = 0; f < keyCount; ++f) {
vals[f] = r.getNormalFieldValue(f);
}
if (Variant.compareArrays(vals, keys, keyCount) == 0) {
mid = i;
} else {
break;
}
}
} else { // ?ҽ???λ??
for (int i = mid + 1; i <= high; ++i) {
r = (BaseRecord)mems.get(i);
for (int f = 0; f < keyCount; ++f) {
vals[f] = r.getNormalFieldValue(f);
}
if (Variant.compareArrays(vals, keys, keyCount) == 0) {
mid = i;
} else {
break;
}
}
if (mid < len) mid++;
}
return mid; // key found
}
}
if (low < len + 1) {
return low;
} else {
return -1;
}
}
//????ֵ???ҿ?ź?λ?ã?????????????????
//key[] Ҫ???ҵ?ֵ
//icount ?ֶθ???
//isStart ?Ƿ????ҿ?ʼ
//index[] ????ҵ??ļ?¼??
private int searchValue(Object[] key, int icount, boolean isStart) {
int i;
int index = -1;
while (true) {
if (icount == 1) {
i = binarySearch(key[0]);
if (i < 0) {
break;
}
} else {
i = binarySearchArray(key, isStart);
if (i < 0) {
break;
}
}
index = i;
break;
}
return index;
}
/**
* ??????ʽexp??ѯ
*/
public ICursor select(Expression exp, String []fields, String opt, Context ctx) {
IntArray recNums = null;
ICursor cs;
if (type == TYPE_FULLTEXT) {
cs = select_fulltext(exp, fields, opt, ctx);
} else {
if (type == TYPE_SORT)
recNums = select_sort(exp, opt, ctx);
else if (type == TYPE_HASH)
recNums = select_hash(exp, opt, ctx);
if (recNums == null || recNums.size() == 0) {
return new MemoryCursor(null);
}
Table srcTable = this.srcTable;
Table result = new Table(srcTable.dataStruct());
if (type == TYPE_HASH) {
for (int i = recNums.size(); i > 0; i--) {
BaseRecord rec = srcTable.getRecord(recNums.getInt(i));
result.add(rec);
}
} else {
for (int i = 1, len = recNums.size(); i <= len; i++) {
BaseRecord rec = srcTable.getRecord(recNums.getInt(i));
result.add(rec);
}
}
cs = new MemoryCursor(result);
}
if (fields != null) {
int len = fields.length;
Expression[] exps = new Expression[len];
for (int i = 0; i < len; i++) {
exps[i] = new Expression(fields[i]);
}
New op = new New(exps, fields, null);
cs.addOperation(op, ctx);
}
return cs;
}
/**
* ??????ʽ??ѯ
* @param exp
* @param opt
* @param ctx
* @return ??¼??
*/
private IntArray select_sort(Expression exp, String opt, Context ctx) {
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 (icount != split.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.paramCountNotMatch"));
}
if (0 != Variant.compareArrays(ifields, split)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
series.sort("o");
return select(series, 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(new String[]{fmtExp}, exp, opt, 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, opt, ctx);
}
Sequence series = new Sequence();
series.add(seq);
return select(series, opt, ctx);
}
return select(vals, 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, opt, ctx);
}
}
}
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;
int end;
start = 1;
end = indexData.length();
int eqCount = vals.length();
if (eqCount == 0) {
if (ff != null && ff.startSign != NULL) {
Object []keys = new Object[]{ff.startVal};
start = searchValue(keys, icount, true);
if (start < 0) return null;
}
if (ff != null && ff.endSign != NULL) {
Object []keys = new Object[]{ff.endVal};
end = searchValue(keys, icount, false);
if (end < 0) end = indexData.length();
}
} else {
if (ff == null || ff.startSign == NULL) {
Object []keys = vals.toArray();
start = searchValue(keys, icount, true);
} else {
Object []keys = new Object[eqCount + 1];
vals.toArray(keys);
keys[eqCount] = ff.startVal;
start = searchValue(keys, eqCount + 1, true);
}
if (start < 0) return null;
if (ff == null || ff.endSign == NULL) {
if (icount == 1) {
end = start;
} else {
Object []keys = vals.toArray();
end = searchValue(keys, icount, false);
}
} else {
Object []keys = new Object[eqCount + 1];
vals.toArray(keys);
keys[eqCount] = ff.endVal;
end = searchValue(keys, icount, false);
}
if (end < 0) end = indexData.length();//(int) (this.internalBlockCount - 1);
}
IntArray recNum = null;
if (start >= 0) {
recNum = select(start, end, exp, ctx);
}
return recNum;
}
/**
* ??????ʽ??ѯ
*/
private IntArray select_hash(Expression exp, String opt, Context ctx) {
int icount = ifields.length;
if (icount == 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("Expression.unknownExpression") + exp.toString());
}
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 (icount != split.length) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.paramCountNotMatch"));
}
if (0 != Variant.compareArrays(ifields, split)) {
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
// series.sort("o");
return select_hash(series, opt, ctx);
}
ArrayList objs = new ArrayList();
if (getFieldFilters(exp.getHome(), objs, ctx)) {
Object[] vals;
int size = objs.size();
if (size == 0) {
return null;
} else {
vals = new Object[size];
objs.toArray(vals);
}
return select_hash(vals, opt, ctx);
}
MessageManager mm = EngineMessage.get();
throw new RQException("icursor" + mm.getMessage("function.invalidParam"));
}
/**
* ??ֵ?????ѯ?????ֶΣ?
* @param startVals
* @param endVals
* @param opt
* @param ctx
* @return
*/
private IntArray select(Object []startVals, Object []endVals, String opt, Context ctx) {
boolean le = opt == null || opt.indexOf('l') == -1;
boolean re = opt == null || opt.indexOf('r') == -1;
int icount = ifields.length;
IntArray srcPos = null;
if (startVals == null) {
throw new RQException("icursor: never run to here!");
} else if (endVals == null) {
throw new RQException("icursor: never run to here!");
} 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 new IntArray();
} else if (cmp == 0 && (!le || !re)) {
return new IntArray();
}
int start;
int end;
start = searchValue(startVals, icount, true);
if (start < 0) return new IntArray();
end = searchValue(endVals, icount, false);
if (start >= 0) {
if (end < 0) {
srcPos = readPos(startVals, start, le ? GE : GT);
} else {
srcPos = readPos(startVals, start, le, endVals, end, re);
}
}
}
return srcPos;
}
/**
* һ?β?ѯ???ֵ
* @param vals
* @param opt
* @param ctx
* @return
*/
private IntArray select(Sequence vals, String opt, Context ctx) {
if (vals == null || vals.length() == 0) return null;
IArray mems = vals.getMems();
int len = vals.length();
IntArray recNum = new IntArray(len * avgNums);
IntArray[] recordNums = this.recordNums;
for (int i = 1; i <= len; i++) {
Object srcVal = mems.get(i);
int pos = indexTable.findPos(srcVal);
if (pos != 0) {
recNum.addAll(recordNums[pos]);
}
}
return recNum;
}
private IntArray select_hash(Sequence vals, String opt, Context ctx) {
if (vals == null || vals.length() == 0) return null;
IArray mems = vals.getMems();
int len = vals.length();
IntArray recNum = new IntArray(len * avgNums);
for (int i = len; i > 0; i--) {
Object srcVal = mems.get(i);
indexTable.findPos(srcVal, recNum);
}
return recNum;
}
private IntArray select(Object key, boolean isFirst, Context ctx) {
if (key == null) return null;
IntArray recNum = new IntArray(avgNums);
int pos;
if (key instanceof Object[]) {
pos = indexTable.findPos((Object[])key);
} else {
pos = indexTable.findPos(key);
}
if (pos > 0) {
IntArray[] recordNums = this.recordNums;
if (isFirst) {
recNum.add(recordNums[pos].get(1));
} else {
recNum.addAll(recordNums[pos]);
}
return recNum;
} else {
return null;
}
}
private IntArray select_hash(Object key, boolean isFirst, Context ctx) {
if (key == null) return null;
IntArray recNum = new IntArray(avgNums);
indexTable.findPos(key, recNum);
int size = recNum.size();
if (size == 0) return null;
if (isFirst && size != 1) {
recNum.setSize(1);
return recNum;
} else {
return recNum;
}
}
private IntArray select(Object[] vals, String opt, Context ctx) {
if (vals == null || vals.length == 0) return null;
int len = vals.length;
IntArray recNum = new IntArray(len * avgNums);
IntArray[] recordNums = this.recordNums;
for (int i = 0; i < len; i++) {
int pos = indexTable.findPos(vals[i]);
if (pos != 0) {
recNum.addAll(recordNums[pos]);
}
}
return recNum;
}
private IntArray select_hash(Object[] vals, String opt, Context ctx) {
if (vals == null || vals.length == 0) return null;
int len = vals.length;
IntArray recNum = new IntArray(len * avgNums);
for (int i = len - 1; i >= 0; i--) {
indexTable.findPos(vals[i], recNum);
}
return recNum;
}
/**
*
* @param start ??????
* @param end ??????
* @return
*/
private IntArray select(int start, int end, Expression exp, Context ctx) {
if (start > end) return null;
int len = end - start + 1;
IntArray resultNum = new IntArray(len * avgNums);
IntArray[] recordNums = this.recordNums;
for (int i = start; i <= end; i++) {
IntArray recNum = recordNums[i];
int size = recNum.size();
for (int j = 1; j <= size; j++) {
int seq = recNum.getInt(j);
BaseRecord rec = srcTable.getRecord(seq);
Object b = rec.calc(exp, ctx);
if (Variant.isTrue(b)) {
resultNum.addInt(seq);
}
}
}
return resultNum;
}
/**
* ??????key[0]??ͷ??
* @param key key[0]??String
* @param exp like????ʽ
* @param ctx
* @return ??ַ(α??)????
*/
private IntArray select(String []key, Expression exp, String opt, Context ctx) {
int start = 0;
IntArray srcPos = null;
start = searchValue(key, 1, true);
if (start < 0) return new IntArray();
if (start >= 0) {
readPos_like(start, exp, ctx);
}
return srcPos;
}
private IntArray readPos_like(int start, Expression exp, Context ctx) {
IntArray recNum = recordNums[start];
Table srcTable = this.srcTable;
IntArray resultNum = new IntArray();
DataStruct ds = new DataStruct(ifields);
Record r = new Record(ds);
ComputeStack stack = ctx.getComputeStack();
stack.push(r);
try {
for (int i = 1, len = recNum.size(); i <= len; i++) {
int seq = recNum.getInt(i);
BaseRecord rec = srcTable.getRecord(seq);
Object cur = rec.getNormalFieldValue(0);
r.setNormalFieldValue(0, cur);
Object b = exp.calculate(ctx);
if (Variant.isTrue(b)) {
resultNum.addInt(seq);
}
}
} finally {
stack.pop();
}
return resultNum;
}
//?ж??Ƿ???indexData??ָ??ֵ???
private boolean isEqualToIndexData(int seq, Object[] vals) {
BaseRecord rec = indexData.getRecord(seq);
Object[] cur = rec.getFieldValues();
int keyCount = vals.length;
int cmp = Variant.compareArrays(vals, cur, keyCount);
return cmp == 0;
}
private int compareToIndexData(int seq, Object[] vals) {
BaseRecord rec = indexData.getRecord(seq);
Object[] cur = rec.getFieldValues();
int keyCount = vals.length;
int cmp = Variant.compareArrays(cur, vals, keyCount);
return cmp;
}
private IntArray readPos(Object[] startVals, int start, int type) {
IntArray[] recordNums = this.recordNums;
int end = recordNums.length;
int len = end - start + 1;
IntArray recNum;
switch (type) {
case EQ:
if (isEqualToIndexData(start, startVals))
return recordNums[start];
else
return null;
case GE:
recNum = new IntArray(len * avgNums);
if (compareToIndexData(start, startVals) >= 0)
recNum.addAll(recordNums[start]);
start++;
for (int i = start; i <= end; i++) {
recNum.addAll(recordNums[i]);
}
return recNum;
case GT:
recNum = new IntArray(len * avgNums);
if (compareToIndexData(start, startVals) > 0)
recNum.addAll(recordNums[start]);
start++;
for (int i = start; i <= end; i++) {
recNum.addAll(recordNums[i]);
}
return recNum;
case LE:
recNum = new IntArray(start * avgNums);
for (int i = 1; i < start; i++) {
recNum.addAll(recordNums[i]);
}
if (compareToIndexData(start, startVals) <= 0)
recNum.addAll(recordNums[start]);
return recNum;
case LT:
recNum = new IntArray(start * avgNums);
for (int i = 1; i < start; i++) {
recNum.addAll(recordNums[i]);
}
if (compareToIndexData(start, startVals) < 0)
recNum.addAll(recordNums[start]);
return recNum;
}
throw new RuntimeException();
}
private IntArray readPos(Object[] startVals, int start, boolean le, Object[] endVals, int end, boolean re) {
IntArray[] recordNums = this.recordNums;
int len = end - start + 1;
IntArray recNum = new IntArray(len * avgNums);
int i = start;
if (le) {
if (compareToIndexData(i, startVals) >= 0)
recNum.addAll(recordNums[i]);
} else {
if (compareToIndexData(i, startVals) > 0)
recNum.addAll(recordNums[i]);
}
i++;
for (; i < end; i++) {
recNum.addAll(recordNums[i]);
}
if (re) {
if (compareToIndexData(i, endVals) <= 0)
recNum.addAll(recordNums[i]);
} else {
if (compareToIndexData(i, endVals) < 0)
recNum.addAll(recordNums[i]);
}
return recNum;
}
private ICursor toCursor(Sequence srcTable, Expression exp, Context ctx) {
return (ICursor) new MemoryCursor(srcTable).select(null, exp, null, ctx);
}
private ICursor select_fulltext(Expression exp, String []fields, String opt, Context ctx) {
int icount = ifields.length;
if (icount == 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(mm.getMessage("Expression.unknownExpression") + exp.toString());
}
Node home = exp.getHome();
//????like(F,"*xxx*")????ʽ
while (home instanceof Like) {
if (((Like) home).getParam().getSubSize() != 2) {
break;
}
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])) {
break;
}
//??????like("*?ؼ???*")??ʽ?ġ?????????ͨ?Ĵ???
String fmtExp = (String) sub2.getLeafExpression().calculate(ctx);
int idx = fmtExp.indexOf("*");
if (idx != 0) {
//return srcTable.cursor(fields, exp, ctx);
return toCursor(srcTable, exp, ctx);
}
fmtExp = fmtExp.substring(1);
idx = fmtExp.indexOf("*");
if (idx != fmtExp.length() - 1) {
//return srcTable.cursor(fields, exp, ctx);
return toCursor(srcTable, exp, ctx);
}
fmtExp = fmtExp.substring(0, fmtExp.length() - 1);
idx = fmtExp.indexOf("*");
if (idx >= 0) {
//return srcTable.cursor(fields, exp, ctx);
return toCursor(srcTable, exp, ctx);
}
String regex = "[a-zA-Z0-9]+";
if (fmtExp.matches(regex) && fmtExp.length() < 3) {
//return srcTable.cursor(fields, exp, ctx);
return toCursor(srcTable, exp, ctx);
}
IntArray recNums = select_fulltext(exp, opt, ctx);
if (recNums != null && recNums.size() > 0) {
Table srcTable = this.srcTable;
Table result = new Table(srcTable.dataStruct());
for (int i = 1, len = recNums.size(); i <= len; i++) {
BaseRecord rec = srcTable.getRecord(recNums.getInt(i));
result.add(rec);
}
ICursor cs = new MemoryCursor(result);
Select select = new Select(exp, null);
cs.addOperation(select, ctx);
return cs;
} else {
return null;
}
}
return toCursor(srcTable, exp, ctx);//return srcTable.cursor(fields, exp, ctx);
}
private static IntArray intArrayUnite(IntArray a, IntArray b) {
int lenB = b.size();
if (a == null) {
IntArray c = new IntArray(lenB);
c.addAll(b);
return c;
}
int lenA = a.size();
if (lenB == 0) {
return a;
}
IntArray c = new IntArray(Math.min(lenA, lenB));
int i = 1, j = 1;
while (i <= lenA && j <= lenB) {
int longA = a.getInt(i);
int longB = a.getInt(j);
if (longA < longB) {
i++;
} else if (longB < longA) {
j++;
} else {
c.add(a.getInt(i));
i++;
j++;
}
}
return c;
}
private IntArray select_fulltext(Expression exp, String opt, Context ctx) {
String f = ifields[0];
IParam sub2 = ((Like) exp.getHome()).getParam().getSub(1);
String fmtExp = (String) sub2.getLeafExpression().calculate(ctx);
fmtExp = fmtExp.substring(1, fmtExp.length() - 1);
// boolean isRow = srcTable instanceof RowPhyTable;
// long recCountOfSegment[] = null;
// if (!isRow) {
// recCountOfSegment = ((ColPhyTable)srcTable).getSegmentInfo();
// }
//??ÿ???ؼ??ַ????й??ˣ???
String regex = "[a-zA-Z0-9]+";
String search = "";
IntArray tempPos = null;
int strLen = fmtExp.length();
int j;
int p = 0;//??ʾ????????λ??
for (j = 0; j < strLen; ) {
String str = fmtExp.substring(j, j + 1);
p = j + 1;
if (str.matches(regex)) {
//Ӣ??
//????????ȡ4????ĸ
if (j + 3 < strLen) {
String str4 = fmtExp.substring(j, j + 4);
if (str4.matches(regex)) {
str = str4;
p = j + 4;
}
} else if (j + 2 < strLen) {//????????ȡ3????ĸ
String str3 = fmtExp.substring(j, j + 3);
if (str3.matches(regex)) {
str = str3;
p = j + 3;
}
}
}
j++;
if (search.indexOf(str) >= 0) {
continue;//?ظ??IJ??ٲ?ѯ
}
search = fmtExp.substring(0, p);
Expression tempExp = new Expression(f + "==\"" + str + "\"");
IntArray srcPos = select_sort(tempExp, opt, null);
if (srcPos == null || srcPos.size() == 0) {
tempPos = null;
break;
}
//???鲢??
tempPos = intArrayUnite(tempPos, srcPos);
}
return tempPos;
}
/**
* ????KEYֵ??ѯ??¼??
* @param key keyֵ
* @param opt ѡ??
* @param ctx
* @return ??¼(??)????
*/
public Object ifind(Object key, String opt, Context ctx) {
IntArray recNums = null;
boolean hasOpt1 = false;
boolean hasOptP = false;
if (opt != null) {
hasOpt1 = opt.indexOf('1') != -1;
hasOptP = opt.indexOf('p') != -1;
}
if (type == TYPE_FULLTEXT) {
String option = "p";
if (hasOpt1) option += "z";
return (Sequence) srcTable.pos(key, option);
} else {
if (type == TYPE_SORT)
recNums = select(key, hasOpt1, ctx);
else if (type == TYPE_HASH)
recNums = select_hash(key, hasOpt1, ctx);
}
if (recNums == null || recNums.size() == 0) return null;
if (hasOptP) {
//???????
if (hasOpt1)
return recNums.getInt(1);
else
return new Sequence(recNums);
} else {
//???ؼ?¼
if (hasOpt1) {
return srcTable.getRecord(recNums.getInt(1));
}
Table srcTable = this.srcTable;
Table result = new Table(srcTable.dataStruct());
for (int i = 1, len = recNums.size(); i <= len; i++) {
BaseRecord rec = srcTable.getRecord(recNums.getInt(i));
result.add(rec);
}
return result;
}
}
public int getType() {
return type;
}
public IndexTable getIndexTable() {
return indexTable;
}
}