com.scudata.expression.mfn.file.ISelect 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.expression.mfn.file;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import com.scudata.common.MessageManager;
import com.scudata.common.RQException;
import com.scudata.dm.BFileReader;
import com.scudata.dm.BaseRecord;
import com.scudata.dm.Context;
import com.scudata.dm.DataStruct;
import com.scudata.dm.FileObject;
import com.scudata.dm.IFile;
import com.scudata.dm.LineImporter;
import com.scudata.dm.Record;
import com.scudata.dm.Sequence;
import com.scudata.dm.Table;
import com.scudata.dm.cursor.FileCursor;
import com.scudata.dm.cursor.ICursor;
import com.scudata.dm.cursor.MemoryCursor;
import com.scudata.expression.Expression;
import com.scudata.expression.FileFunction;
import com.scudata.expression.IParam;
import com.scudata.resources.EngineMessage;
import com.scudata.util.Variant;
/**
* ?ӶԱ???ʽ??????ļ????ı??ļ????ļ????в??Ҽ?¼
* f.iselect(A,x;Fi,??;s) ????x??????A?еļ?¼?????α?
* f.iselect(a:b,x;Fi,??;s) ????x??[a,b]????ļ?¼?????α?
* @author RunQian
*
*/
public class ISelect extends FileFunction {
public Object calculate(Context ctx) {
if (param == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.missingParam"));
}
IParam valParam;
String []selFields = null;
String s = null;
if (param.getType() == IParam.Semicolon) {
valParam = param.getSub(0);
IParam fieldParam = param.getSub(1);
if (fieldParam == null) {
} else if (fieldParam.isLeaf()) {
selFields = new String[]{fieldParam.getLeafExpression().getIdentifierName()};
} else {
int size = fieldParam.getSubSize();
selFields = new String[size];
for (int i = 0; i < size; ++i) {
IParam sub = fieldParam.getSub(i);
if (sub == null || !sub.isLeaf()) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.invalidParam"));
}
selFields[i] = sub.getLeafExpression().getIdentifierName();
}
}
if (param.getSubSize() > 2) {
IParam sParam = param.getSub(2);
if (sParam != null) {
Object obj = sParam.getLeafExpression().calculate(ctx);
if (!(obj instanceof String)) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.paramTypeError"));
}
s = (String)obj;
}
}
} else {
valParam = param;
}
if (valParam.getSubSize() != 2) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.invalidParam"));
}
IParam sub0 = valParam.getSub(0);
IParam sub1 = valParam.getSub(1);
if (sub0 == null || sub1 == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.invalidParam"));
}
if (sub0.isLeaf()) {
Object key = sub0.getLeafExpression().calculate(ctx);
Sequence values;
if (key == null) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.invalidParam"));
}
if (key instanceof Sequence) {
values = (Sequence)key;
} else {
values = new Sequence(1);
values.add(key);
}
Expression exp = sub1.getLeafExpression();
if (null == exp){
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.paramTypeError"));
}
return search(file, exp, values, selFields, s, option, ctx);
} else {
if (sub0.getSubSize() != 2) {
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.invalidParam"));
}
Object startVal = null;
Object endVal = null;
IParam startParam = sub0.getSub(0);
if (startParam != null) {
startVal = startParam.getLeafExpression().calculate(ctx);
}
IParam endParam = sub0.getSub(1);
if (endParam != null) {
endVal = endParam.getLeafExpression().calculate(ctx);
}
Expression exp = sub1.getLeafExpression();
if (null == exp){
MessageManager mm = EngineMessage.get();
throw new RQException("iselect" + mm.getMessage("function.paramTypeError"));
}
return search(file, exp, startVal, endVal, selFields, s, option, ctx);
}
}
private static ICursor search(FileObject fo, Expression exp, Sequence values,
String []selFields, String s, String opt, Context ctx) {
boolean isCsv = false;
boolean isMultiId = false;
boolean isExist = true;
if (opt != null) {
if (opt.indexOf('b') != -1) {
BFileReader reader = new BFileReader(fo);
return reader.iselect(exp, values, selFields, ctx);
}
if (opt.indexOf('c') != -1) isCsv = true;
if (opt.indexOf('e') != -1) isExist = false;
if (opt.indexOf('r') != -1) isMultiId = true;
}
String charset = fo.getCharset();
byte[] separator;
if (s != null && s.length() > 0) {
try {
separator = s.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RQException(e.getMessage(), e);
}
} else if (isCsv) {
separator = new byte[]{(byte)','};
} else {
separator = FileObject.COL_SEPARATOR;
}
Table table = iselect_t(fo, exp, values, separator, opt, isMultiId, ctx);
if (selFields != null) {
DataStruct ds = table.dataStruct();
int fcount = selFields.length;
int []index = new int[fcount];
String []names = ds.getFieldNames();
for (int f = 0; f < fcount; ++f) {
index[f] = ds.getFieldIndex(selFields[f]);
if (index[f] < 0) {
if (isExist) {
MessageManager mm = EngineMessage.get();
throw new RQException(selFields[f] + mm.getMessage("ds.fieldNotExist"));
}
} else {
selFields[f] = names[index[f]];
}
}
int len = table.length();
Table selTable = new Table(selFields, len);
for (int i = 1; i <= len; ++i) {
BaseRecord nr = selTable.newLast();
BaseRecord r = (BaseRecord)table.get(i);
for (int f = 0; f < fcount; ++f) {
if (index[f] >= 0) {
nr.setNormalFieldValue(f, r.getFieldValue(index[f]));
}
}
}
table = selTable;
}
if (table != null && table.length() > 0) {
return new MemoryCursor(table);
} else {
return null;
}
}
/**
* ???ݶԱ????ݺͶԱȱ???ʽ???ļ??в??ҽ?????????cursor???
*
* @param fo ?ļ?????
* @param fieldName ?Աȱ???ʽ
* @param startVal ??ʼֵ
* @param endVal ????ֵ
* @param selFields ??ɽ?????ֶ?
* @param s
* @param opt ??ȡ?ļ?????
* @param ctx ?????ı???
* @return ???ؽ??cursor
*/
private static ICursor search(FileObject fo, Expression exp, Object startVal,
Object endVal, String []selFields, String s, String opt, Context ctx) {
boolean isCsv = false;
if (opt != null) {
// ????Ƕ??????ļ??????ɶ??????ļ???cursor
if (opt.indexOf('b') != -1) {
BFileReader reader = new BFileReader(fo);
return reader.iselect(exp, startVal, endVal, selFields, ctx);
}
if (opt.indexOf('c') != -1) isCsv = true;
}
String charset = fo.getCharset();
byte[] separator;
if (s != null && s.length() > 0) {
try {
separator = s.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RQException(e.getMessage(), e);
}
} else if (isCsv) {
separator = new byte[]{(byte)','};
} else {
separator = FileObject.COL_SEPARATOR;
}
LineImporter importer = null;
Object []line = null;
try {
importer = new LineImporter(fo.getInputStream(), charset, separator, opt, 1024);
line = importer.readLine();
} catch(IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
if (importer != null) {
importer.close();
}
} catch (IOException ie) {
}
}
if (line == null || line.length == 0) {
MessageManager mm = EngineMessage.get();
throw new RQException(exp.getIdentifierName() + mm.getMessage("ds.fieldNotExist"));
}
long start = 0;
if (startVal != null) {
start = iselect_t(fo, exp, startVal, separator, opt, true, ctx);
if (start < 0) {
start = -start;
}
}
long end;
if (endVal != null) {
end = iselect_t(fo, exp, endVal, separator, opt, false, ctx);
if (end < 0) {
end = -end;
}
} else {
end = fo.size();
}
FileCursor cursor = new FileCursor(fo, 0, 0, selFields, null, s, opt, ctx);
cursor.setStart(start);
cursor.setEnd(end);
return cursor;
}
/**
* ???????ļ??У?ȡ?ü?¼????ʽ??ֵ????values?еļ?¼??
* @param fo ?????ļ?????
* @param exp ????ʽ
* @param values ?ο?ֵ
* @param separator ??foΪ?ı??ļ????ñ???Ϊ?ָ???.
* @param opt ?ļ???д????
* @param isMultiId ?Ƿ??ID
* @return ??ȡ?õļ?¼??ɵ?table
*/
private static Table iselect_t(FileObject fo, Expression exp, Sequence values,
byte[] separator, String opt, boolean isMultiId, Context ctx) {
boolean isTitle = false;
if (opt != null) {
if (opt.indexOf('t') != -1) isTitle = true;
}
IFile file = fo.getFile();
String charset = fo.getCharset();
LineImporter importer = null;
Object []line = null;
long start = 0;
Record rec = null;
try {
importer = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
line = importer.readLine();
if (line == null) {
return null;
}
byte []colTypes = new byte[line.length];
importer.setColTypes(colTypes, null);
if (isTitle) {
start = importer.getCurrentPosition() - 2;
}
} catch(IOException e) {
try {
if (importer != null) {
importer.close();
importer = null;
}
} catch (IOException ie) {
}
throw new RQException(e.getMessage(), e);
}
if (line == null || line.length == 0) {
try {
if (importer != null) {
importer.close();
importer = null;
}
} catch (IOException e) {
}
MessageManager mm = EngineMessage.get();
throw new RQException(exp.getIdentifierName() + mm.getMessage("ds.fieldNotExist"));
}
int fcount = line.length;
DataStruct ds;
if (isTitle) {
String[] items = new String[fcount];
for (int f = 0; f < fcount; ++f) {
items[f] = Variant.toString(line[f]);
}
ds = new DataStruct(items);
} else {
String[] items = new String[fcount];
ds = new DataStruct(items);
}
rec = new Record(ds);
int valCount = values.length();
Table table = new Table(ds, valCount);
long size = file.size();
try {
for (int i = 1; i <= valCount; ++i) {
long low = start;
long high = size;
Object key = values.get(i);
boolean isExist = false;
while (low <= high) {
long mid = (low + high) >> 1;
long pos = importer.getCurrentPosition();
if (pos > mid) {
importer.close();
LineImporter tmp = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
tmp.copyProperty(importer);
importer = tmp;
}
if (isMultiId && low == high) {
break;
}
importer.seek(mid);
Object []objs = importer.readLine();
if (objs == null) { // ?????β
high = mid - 1;
} else {
rec.setStart(0, objs);
int cmp = 0;
try {
cmp = Variant.compare(rec.calc(exp, ctx), key);
} catch (RQException e) {
low = mid + 1;
start = low;
continue;
}
if (isMultiId){
if (cmp < 0) {
low = mid + 1;
start = low;
} else if (cmp > 0) {
high = mid;
} else {
high = mid;
isExist = true;
}
} else {
if (cmp < 0) {
low = mid + 1;
start = low;
} else if (cmp > 0) {
high = mid - 1;
} else {
if (objs.length <= fcount) {
table.newLast(objs);
} else {
BaseRecord r = table.newLast();
for (int f = 0; f < fcount; ++f) {
r.setNormalFieldValue(f, objs[f]);
}
}
pos = importer.getCurrentPosition();
if (pos < size) {
start = pos - 2;
} else {
start = size;
}
break;
}
}
}
}
if (isMultiId && isExist){
start = iselect_i(importer, table, low, exp, rec, key, fcount, size, ctx);
}
if (start >= size) {
break;
}
}
} catch(IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
if (importer != null) importer.close();
} catch (Exception e) {
}
}
return table;
}
private static long iselect_i(LineImporter importer, Table table,long pos, Expression exp,
BaseRecord rec, Object key, int fcount, long size, Context ctx) throws IOException {
importer.seek(pos);
while (true) {
long lastpos = importer.getCurrentPosition();
Object []objs = importer.readLine();
if (objs == null) { // ?????β
return importer.getCurrentPosition();
}
try {
rec.setStart(0, objs);
if (Variant.compare(rec.calc(exp, ctx), key) == 0){
lastpos = importer.getCurrentPosition();
if (objs.length <= fcount) {
table.newLast(objs);
} else {
BaseRecord r = table.newLast();
for (int f = 0; f < fcount; ++f) {
r.setNormalFieldValue(f, objs[f]);
}
}
} else {
return lastpos - 2;
}
} catch (RQException e) {
return importer.getCurrentPosition();
}
}
}
/**
* ??һ???ı??ļ??У???λ????ʽexp?Ľ????ӽ?value?ļ?¼??λ??
*
* @param fo ?ı??ļ????ļ?????
* @param exp ????ʽ
* @param value ?ο?ֵ
* @param separator ?ı??ļ??ķָ???
* @param opt ?ļ???ȡ????
* @param isStart true С??value?ļ?¼
* false ????value?ļ?¼
*
* @return ???ض?Ӧ?????λ??
*
*/
private static long iselect_t(FileObject fo, Expression exp, Object value,
byte[] separator, String opt, boolean isStart, Context ctx) {
boolean isTitle = false, isKey = true;
if (opt != null) {
if (opt.indexOf('t') != -1) isTitle = true;
if (opt.indexOf('r') != -1) isKey = false;
}
IFile file = fo.getFile();
String charset = fo.getCharset();
LineImporter importer = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
long low = 0;
long high = file.size();
try {
Object []line = importer.readLine();
if (line == null) {
return -1;
}
byte []colTypes = new byte[line.length];
importer.setColTypes(colTypes, null);
// ??ʼ????¼????
String[] fields = new String[line.length];
if (isTitle) {
low = importer.getCurrentPosition() - 2;
for (int i = 0; i < line.length; i++) {
fields[i] = Variant.toString(line[i]);
}
}
DataStruct ds = new DataStruct(fields);
Record rec = new Record(ds);
while (low <= high) {
long mid = (low + high) >> 1;
long pos = importer.getCurrentPosition();
if (pos > mid) {
importer.close();
LineImporter tmp = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
tmp.copyProperty(importer);
importer = tmp;
}
importer.seek(mid);
Object []objs = importer.readLine();
if (objs == null) { // ?????β
high = mid - 1;
} else {
rec.setStart(0, objs);
int cmp = Variant.compare(rec.calc(exp, ctx), value);
if (cmp < 0) {
low = mid + 1;
} else if (cmp > 0) {
high = mid - 1;
} else {
if (isKey) {
if (isStart) {
return mid;
} else {
return importer.getCurrentPosition() - 2;
}
} else if (isStart) {
// ?ҵ???ǰ????ȵ?
high = mid;
while (low < high) {
mid = (low + high) >> 1;
pos = importer.getCurrentPosition();
if (pos > mid) {
importer.close();
LineImporter tmp = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
tmp.copyProperty(importer);
importer = tmp;
}
importer.seek(mid);
objs = importer.readLine();
rec.setStart(0, objs);
cmp = Variant.compare(rec.calc(exp, ctx), value);
if (cmp < 0) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
} else {
// ?ҵ????һ????ȵ?
long result = importer.getCurrentPosition() - 2;
low = mid;
while (low < high) {
mid = (low + high) >> 1;
pos = importer.getCurrentPosition();
if (pos > mid) {
importer.close();
LineImporter tmp = new LineImporter(file.getInputStream(), charset, separator, opt, 1024);
tmp.copyProperty(importer);
importer = tmp;
}
importer.seek(mid);
objs = importer.readLine();
if (objs == null) {
break;
}
rec.setStart(0, objs);
cmp = Variant.compare(rec.calc(exp, ctx), value);
if (cmp > 0) {
high = mid;
} else {
low = mid + 1;
result = importer.getCurrentPosition() - 2;
}
}
return result;
}
}
}
}
} catch(IOException e) {
throw new RQException(e.getMessage(), e);
} finally {
try {
if (importer != null) importer.close();
} catch (IOException e) {
}
}
return -low;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy