未验证 提交 1cc1d852 编写于 作者: J jaugsburger 提交者: GitHub

fix(griffin) - partial/short date in where clause >=, > ,<, <= #323 #265 (#333)

上级 2850229c
......@@ -156,7 +156,7 @@ final class WhereClauseParser implements Mutable {
return false;
}
private boolean analyzeGreater(IntrinsicModel model, ExpressionNode node, int increment) throws SqlException {
private boolean analyzeGreater(IntrinsicModel model, ExpressionNode node, boolean equalsTo) throws SqlException {
checkNodeValid(node);
if (nodesEqual(node.lhs, node.rhs)) {
......@@ -175,7 +175,8 @@ final class WhereClauseParser implements Mutable {
}
try {
model.intersectIntervals(TimestampFormatUtils.tryParse(node.rhs.token, 1, node.rhs.token.length() - 1), Long.MAX_VALUE);
long lo = parseFullOrPartialDate(equalsTo, node.rhs, true);
model.intersectIntervals(lo, Long.MAX_VALUE);
node.intrinsicValue = IntrinsicModel.TRUE;
return true;
} catch (NumericException e) {
......@@ -190,7 +191,9 @@ final class WhereClauseParser implements Mutable {
}
try {
model.intersectIntervals(Long.MIN_VALUE, TimestampFormatUtils.tryParse(node.lhs.token, 1, node.lhs.token.length() - 1) - increment);
long hi = parseFullOrPartialDate(equalsTo, node.lhs, false);
model.intersectIntervals(Long.MIN_VALUE, hi);
node.intrinsicValue = IntrinsicModel.TRUE;
return true;
} catch (NumericException e) {
throw SqlException.invalidDate(node.lhs.position);
......@@ -199,6 +202,21 @@ final class WhereClauseParser implements Mutable {
return false;
}
private long parseFullOrPartialDate(boolean equalsTo, ExpressionNode node, boolean isLo) throws NumericException {
long ts;
if (node.token.length() - 2 < 20) {
if (equalsTo ^ isLo) {
ts = IntrinsicModel.parseCeilingPartialDate(node.token, 1, node.token.length() - 1);
} else {
ts = IntrinsicModel.parseFloorPartialDate(node.token, 1, node.token.length() - 1);
}
} else {
long inc = equalsTo ? 0 : isLo ? 1 : -1;
ts = TimestampFormatUtils.tryParse(node.token, 1, node.token.length() - 1) + inc;
}
return ts;
}
private boolean analyzeIn(AliasTranslator translator, IntrinsicModel model, ExpressionNode node, RecordMetadata metadata) throws SqlException {
if (node.paramCount < 2) {
......@@ -296,7 +314,7 @@ final class WhereClauseParser implements Mutable {
return false;
}
private boolean analyzeLess(IntrinsicModel model, ExpressionNode node, int inc) throws SqlException {
private boolean analyzeLess(IntrinsicModel model, ExpressionNode node, boolean equalsTo) throws SqlException {
checkNodeValid(node);
......@@ -315,8 +333,7 @@ final class WhereClauseParser implements Mutable {
if (node.rhs.type != ExpressionNode.CONSTANT) {
return false;
}
long hi = TimestampFormatUtils.tryParse(node.rhs.token, 1, node.rhs.token.length() - 1) - inc;
long hi = parseFullOrPartialDate(equalsTo, node.rhs, false);
model.intersectIntervals(Long.MIN_VALUE, hi);
node.intrinsicValue = IntrinsicModel.TRUE;
return true;
......@@ -330,8 +347,7 @@ final class WhereClauseParser implements Mutable {
if (node.lhs.type != ExpressionNode.CONSTANT) {
return false;
}
long lo = TimestampFormatUtils.tryParse(node.lhs.token, 1, node.lhs.token.length() - 1);
long lo = parseFullOrPartialDate(equalsTo, node.lhs, true);
model.intersectIntervals(lo, Long.MAX_VALUE);
node.intrinsicValue = IntrinsicModel.TRUE;
return true;
......@@ -673,13 +689,13 @@ final class WhereClauseParser implements Mutable {
case INTRINCIC_OP_IN:
return analyzeIn(translator, model, node, m);
case INTRINCIC_OP_GREATER:
return analyzeGreater(model, node, 1);
return analyzeGreater(model, node, false);
case INTRINCIC_OP_GREATER_EQ:
return analyzeGreater(model, node, 0);
return analyzeGreater(model, node, true);
case INTRINCIC_OP_LESS:
return analyzeLess(model, node, 1);
return analyzeLess(model, node, false);
case INTRINCIC_OP_LESS_EQ:
return analyzeLess(model, node, 0);
return analyzeLess(model, node, true);
case INTRINCIC_OP_EQUAL:
return analyzeEquals(translator, model, node, m);
case INTRINCIC_OP_NOT_EQ:
......
......@@ -318,6 +318,173 @@ public class IntrinsicModel implements Mutable {
}
}
public static long parseFloorPartialDate(CharSequence seq, final int pos, int lim) throws NumericException {
long ts;
if (lim - pos < 4) {
throw NumericException.INSTANCE;
}
int p = pos;
int year = Numbers.parseInt(seq, p, p += 4);
boolean l = Timestamps.isLeapYear(year);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, '-');
int month = Numbers.parseInt(seq, p, p += 2);
checkRange(month, 1, 12);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, '-');
int day = Numbers.parseInt(seq, p, p += 2);
checkRange(day, 1, Timestamps.getDaysPerMonth(month, l));
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, 'T');
int hour = Numbers.parseInt(seq, p, p += 2);
checkRange(hour, 0, 23);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, ':');
int min = Numbers.parseInt(seq, p, p += 2);
checkRange(min, 0, 59);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, ':');
int sec = Numbers.parseInt(seq, p, p += 2);
checkRange(sec, 0, 59);
if (p < lim) {
throw NumericException.INSTANCE;
} else {
// seconds
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS
+ min * Timestamps.MINUTE_MICROS
+ sec * Timestamps.SECOND_MICROS);
}
} else {
// minute
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS
+ min * Timestamps.MINUTE_MICROS);
}
} else {
// year + month + day + hour
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS);
}
} else {
// year + month + day
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS);
}
} else {
// year + month
ts = (Timestamps.yearMicros(year, l) + Timestamps.monthOfYearMicros(month, l));
}
} else {
// year
ts = (Timestamps.yearMicros(year, l) + Timestamps.monthOfYearMicros(1, l));
}
return ts;
}
public static long parseCeilingPartialDate(CharSequence seq, final int pos, int lim) throws NumericException {
long ts;
if (lim - pos < 4) {
throw NumericException.INSTANCE;
}
int p = pos;
int year = Numbers.parseInt(seq, p, p += 4);
boolean l = Timestamps.isLeapYear(year);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, '-');
int month = Numbers.parseInt(seq, p, p += 2);
checkRange(month, 1, 12);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, '-');
int day = Numbers.parseInt(seq, p, p += 2);
checkRange(day, 1, Timestamps.getDaysPerMonth(month, l));
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, 'T');
int hour = Numbers.parseInt(seq, p, p += 2);
checkRange(hour, 0, 23);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, ':');
int min = Numbers.parseInt(seq, p, p += 2);
checkRange(min, 0, 59);
if (checkLen(p, lim)) {
checkChar(seq, p++, lim, ':');
int sec = Numbers.parseInt(seq, p, p += 2);
checkRange(sec, 0, 59);
if (p < lim) {
throw NumericException.INSTANCE;
} else {
// seconds
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS
+ min * Timestamps.MINUTE_MICROS
+ sec * Timestamps.SECOND_MICROS
+ 999999);
}
} else {
// minute
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS
+ min * Timestamps.MINUTE_MICROS
+ 59 * Timestamps.SECOND_MICROS
+ 999999);
}
} else {
// year + month + day + hour
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (day - 1) * Timestamps.DAY_MICROS
+ hour * Timestamps.HOUR_MICROS
+ 59 * Timestamps.MINUTE_MICROS
+ 59 * Timestamps.SECOND_MICROS
+ 999999);
}
} else {
// year + month + day
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ +(day - 1) * Timestamps.DAY_MICROS
+ 23 * Timestamps.HOUR_MICROS
+ 59 * Timestamps.MINUTE_MICROS
+ 59 * Timestamps.SECOND_MICROS
+ 999999);
}
} else {
// year + month
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(month, l)
+ (Timestamps.getDaysPerMonth(month, l) - 1) * Timestamps.DAY_MICROS
+ 23 * Timestamps.HOUR_MICROS
+ 59 * Timestamps.MINUTE_MICROS
+ 59 * Timestamps.SECOND_MICROS
+ 999999);
}
} else {
// year
ts = (Timestamps.yearMicros(year, l)
+ Timestamps.monthOfYearMicros(12, l)
+ (Timestamps.getDaysPerMonth(12, l) - 1) * Timestamps.DAY_MICROS
+ 23 * Timestamps.HOUR_MICROS
+ 59 * Timestamps.MINUTE_MICROS
+ 59 * Timestamps.SECOND_MICROS
+ 999999);
}
return ts;
}
static void append(LongList list, long lo, long hi) {
int n = list.size();
if (n > 0) {
......
......@@ -109,7 +109,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"sym\tprice\tts\n",
"x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by 1 desc",
"x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by 1 desc",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -218,7 +218,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"sym\tprice\tts\n",
"x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by 1",
"x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by 1",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -307,7 +307,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"k\tprice\tts\n",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by k",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by k",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -396,7 +396,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"k\tprice\tts\n",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by k, ts",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by k, ts",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -485,7 +485,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"k\tprice\tts\n",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by k, ts desc",
"select sym k, price, ts from x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by k, ts desc",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -537,7 +537,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"k\tprice\tts\n",
"select sym k, price, ts from x where sym = 'HBC' and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by k, ts desc",
"select sym k, price, ts from x where sym = 'HBC' and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by k, ts desc",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -712,7 +712,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"k\tprice\tts\n",
"select sym k, price, ts from x where sym = 'HBC' and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by k, ts",
"select sym k, price, ts from x where sym = 'HBC' and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by k, ts",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......@@ -801,7 +801,7 @@ public class OrderByAdviceTest extends AbstractGriffinTest {
assertQuery(
"sym\tprice\tts\n",
"x where sym in ('HBC', 'ABB') and ts>'1970-01-04T00:00:00.000Z' and ts<'1970-01-04T10:30:00.000Z' order by sym",
"x where sym in ('HBC', 'ABB') and ts>='1970-01-04T00:00:00.000Z' and ts< '1970-01-04T10:30:00.000Z' order by sym",
"create table x (\n" +
" sym symbol index,\n" +
" price double,\n" +
......
......@@ -513,13 +513,13 @@ public class WhereClauseParserTest extends AbstractCairoTest {
@Test
public void testIntervalGreater1() throws Exception {
IntrinsicModel m = modelOf("timestamp in ('2014-01-01T12:30:00.000Z', '2014-01-02T12:30:00.000Z') and timestamp > '2014-01-01T15:30:00.000Z'");
TestUtils.assertEquals("[{lo=2014-01-01T15:30:00.000000Z, hi=2014-01-02T12:30:00.000000Z}]", GriffinParserTestUtils.intervalToString(m.intervals));
TestUtils.assertEquals("[{lo=2014-01-01T15:30:00.000001Z, hi=2014-01-02T12:30:00.000000Z}]", GriffinParserTestUtils.intervalToString(m.intervals));
}
@Test
public void testIntervalGreater2() throws Exception {
IntrinsicModel m = modelOf("timestamp > '2014-01-01T15:30:00.000Z' and timestamp in ('2014-01-01T12:30:00.000Z', '2014-01-02T12:30:00.000Z')");
TestUtils.assertEquals("[{lo=2014-01-01T15:30:00.000000Z, hi=2014-01-02T12:30:00.000000Z}]", GriffinParserTestUtils.intervalToString(m.intervals));
TestUtils.assertEquals("[{lo=2014-01-01T15:30:00.000001Z, hi=2014-01-02T12:30:00.000000Z}]", GriffinParserTestUtils.intervalToString(m.intervals));
}
@Test
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册