embulk-filter-row 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/CHANGELOG.md +6 -0
- data/README.md +124 -4
- data/build.gradle +15 -4
- data/classpath/embulk-filter-row-0.3.0.jar +0 -0
- data/example/and.yml +0 -7
- data/example/example.yml +0 -7
- data/example/where.yml +28 -0
- data/script/byaccj.sh +29 -0
- data/src/main/java/org/embulk/filter/row/{AbstractColumnVisitor.java → AbstractGuardColumnVisitor.java} +9 -17
- data/src/main/java/org/embulk/filter/row/BuildColumnVisitorImpl.java +98 -0
- data/src/main/java/org/embulk/filter/row/{ColumnVisitorAndImpl.java → GuardColumnVisitorAndImpl.java} +11 -45
- data/src/main/java/org/embulk/filter/row/{ColumnVisitorOrImpl.java → GuardColumnVisitorOrImpl.java} +11 -45
- data/src/main/java/org/embulk/filter/row/GuardColumnVisitorWhereImpl.java +28 -0
- data/src/main/java/org/embulk/filter/row/RowFilterPlugin.java +49 -16
- data/src/main/java/org/embulk/filter/row/where/Parser.java +831 -0
- data/src/main/java/org/embulk/filter/row/where/ParserExp.java +290 -0
- data/src/main/java/org/embulk/filter/row/where/ParserLiteral.java +277 -0
- data/src/main/java/org/embulk/filter/row/where/ParserNode.java +6 -0
- data/src/main/java/org/embulk/filter/row/where/ParserVal.java +78 -0
- data/src/main/java/org/embulk/filter/row/where/Yylex.java +833 -0
- data/src/main/java/org/embulk/filter/row/where/_lexer.l +108 -0
- data/src/main/java/org/embulk/filter/row/where/_parser.y +137 -0
- data/src/test/java/org/embulk/filter/row/where/TestParser.java +383 -0
- data/src/test/java/org/embulk/filter/row/where/TestYylex.java +256 -0
- metadata +19 -5
- data/classpath/embulk-filter-row-0.2.2.jar +0 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
package org.embulk.filter.row.where;
|
2
|
+
|
3
|
+
import org.embulk.spi.Schema;
|
4
|
+
%%
|
5
|
+
|
6
|
+
%byaccj
|
7
|
+
|
8
|
+
%{
|
9
|
+
private StringBuffer string = new StringBuffer();
|
10
|
+
|
11
|
+
protected Parser yyparser;
|
12
|
+
protected Schema schema;
|
13
|
+
|
14
|
+
public Yylex(String str, Parser yyparser) {
|
15
|
+
this(new java.io.StringReader(str));
|
16
|
+
this.yyparser = yyparser;
|
17
|
+
this.schema = yyparser.schema;
|
18
|
+
}
|
19
|
+
%}
|
20
|
+
|
21
|
+
%state STRING
|
22
|
+
%state IDENTIFIER
|
23
|
+
|
24
|
+
Number = -?[0-9]+(\.[0-9]+)?
|
25
|
+
QuotedIdentifierChar = [^\r\n\"\\]
|
26
|
+
NonQuotedIdentifier = [a-zA-Z$][a-zA-z0-9\.\-_]*
|
27
|
+
StringChar = [^\r\n\'\\]+
|
28
|
+
Newline = \n|\r|\r\n
|
29
|
+
|
30
|
+
%%
|
31
|
+
|
32
|
+
<YYINITIAL> {
|
33
|
+
/* operators */
|
34
|
+
"(" { return (int) yycharat(0); }
|
35
|
+
")" { return (int) yycharat(0); }
|
36
|
+
"AND" { return Parser.AND; }
|
37
|
+
"OR" { return Parser.OR; }
|
38
|
+
"=" { return Parser.EQ; }
|
39
|
+
"<>" | "!=" { return Parser.NEQ; }
|
40
|
+
"!=" { return Parser.NEQ; }
|
41
|
+
">" { return Parser.GT; }
|
42
|
+
">=" { return Parser.GE; }
|
43
|
+
"<" { return Parser.LT; }
|
44
|
+
"<=" { return Parser.LE; }
|
45
|
+
"START_WITH" { return Parser.START_WITH; }
|
46
|
+
"END_WITH" { return Parser.END_WITH; }
|
47
|
+
"INCLUDE" { return Parser.INCLUDE; }
|
48
|
+
"IS" { return Parser.IS; }
|
49
|
+
"NOT" { return Parser.NOT; }
|
50
|
+
"NULL" { return Parser.NULL; }
|
51
|
+
"TIMESTAMP" { return Parser.TIMESTAMP; }
|
52
|
+
|
53
|
+
/* boolean literal */
|
54
|
+
"true" | "TRUE" { yyparser.yylval = new ParserVal(new BooleanLiteral(true)); return Parser.BOOLEAN; }
|
55
|
+
"false" | "FALSE" { yyparser.yylval = new ParserVal(new BooleanLiteral(false)); return Parser.BOOLEAN; }
|
56
|
+
|
57
|
+
/* number literal */
|
58
|
+
{Number} { yyparser.yylval = new ParserVal(new NumberLiteral(yytext())); return Parser.NUMBER; }
|
59
|
+
|
60
|
+
/* identifier literal */
|
61
|
+
{NonQuotedIdentifier} { yyparser.yylval = new ParserVal(new IdentifierLiteral(yytext(), schema)); return Parser.IDENTIFIER; }
|
62
|
+
\" { yybegin(IDENTIFIER); string.setLength(0); }
|
63
|
+
|
64
|
+
/* string literal */
|
65
|
+
\' { yybegin(STRING); string.setLength(0); }
|
66
|
+
|
67
|
+
/* whitespace */
|
68
|
+
[ \t]+ { }
|
69
|
+
|
70
|
+
/* newline */
|
71
|
+
{Newline} { }
|
72
|
+
}
|
73
|
+
|
74
|
+
<IDENTIFIER> {
|
75
|
+
\" { yybegin(YYINITIAL); yyparser.yylval = new ParserVal(new IdentifierLiteral(string.toString(), schema)); return Parser.IDENTIFIER; }
|
76
|
+
|
77
|
+
{QuotedIdentifierChar}+ { string.append( yytext() ); }
|
78
|
+
|
79
|
+
/* escape sequences */
|
80
|
+
"\\\"" { string.append( '\"' ); }
|
81
|
+
"\\'" { string.append( '\'' ); }
|
82
|
+
"\\\\" { string.append( '\\' ); }
|
83
|
+
|
84
|
+
/* error cases */
|
85
|
+
\\. { throw new RuntimeException("yylex: Illegal escape sequence \""+yytext()+"\""); }
|
86
|
+
}
|
87
|
+
|
88
|
+
<STRING> {
|
89
|
+
\' { yybegin(YYINITIAL); yyparser.yylval = new ParserVal(new StringLiteral(string.toString())); return Parser.STRING; }
|
90
|
+
|
91
|
+
{StringChar}+ { string.append( yytext() ); }
|
92
|
+
|
93
|
+
/* escape sequences */
|
94
|
+
"\\b" { string.append( '\b' ); }
|
95
|
+
"\\t" { string.append( '\t' ); }
|
96
|
+
"\\n" { string.append( '\n' ); }
|
97
|
+
"\\f" { string.append( '\f' ); }
|
98
|
+
"\\r" { string.append( '\r' ); }
|
99
|
+
"\\\"" { string.append( '\"' ); }
|
100
|
+
"\\'" { string.append( '\'' ); }
|
101
|
+
"\\\\" { string.append( '\\' ); }
|
102
|
+
|
103
|
+
/* error cases */
|
104
|
+
\\. { throw new RuntimeException("yylex: Illegal escape sequence \""+yytext()+"\""); }
|
105
|
+
}
|
106
|
+
|
107
|
+
/* error fallback */
|
108
|
+
[^] { throw new RuntimeException("yylex: Unexpected character '"+yytext()+"'"); }
|
@@ -0,0 +1,137 @@
|
|
1
|
+
%{
|
2
|
+
import org.embulk.spi.Column;
|
3
|
+
import org.embulk.spi.Schema;
|
4
|
+
%}
|
5
|
+
|
6
|
+
/* YACC Declarations */
|
7
|
+
%token EQ /* = */
|
8
|
+
%token NEQ /* <> != */
|
9
|
+
%token GT /* > */
|
10
|
+
%token GE /* >= */
|
11
|
+
%token LT /* < */
|
12
|
+
%token LE /* <= */
|
13
|
+
|
14
|
+
%token START_WITH
|
15
|
+
%token END_WITH
|
16
|
+
%token INCLUDE
|
17
|
+
%token IS
|
18
|
+
%token NOT
|
19
|
+
|
20
|
+
%token AND
|
21
|
+
%token OR
|
22
|
+
|
23
|
+
%token NULL
|
24
|
+
%token BOOLEAN
|
25
|
+
%token STRING
|
26
|
+
%token NUMBER
|
27
|
+
%token IDENTIFIER
|
28
|
+
|
29
|
+
%token TIMESTAMP
|
30
|
+
|
31
|
+
%left OR
|
32
|
+
%left AND
|
33
|
+
%right TIMESTAMP
|
34
|
+
%right NOT
|
35
|
+
|
36
|
+
/* Grammar follows */
|
37
|
+
%%
|
38
|
+
input: /* empty string */
|
39
|
+
| exp { root = $1; }
|
40
|
+
;
|
41
|
+
|
42
|
+
timestamp: TIMESTAMP STRING { $$ = new ParserVal(new TimestampLiteral($2)); }
|
43
|
+
| TIMESTAMP NUMBER { $$ = new ParserVal(new TimestampLiteral($2)); }
|
44
|
+
|
45
|
+
exp: IDENTIFIER EQ BOOLEAN { $$ = new ParserVal(new BooleanOpExp($1, $3, EQ)); }
|
46
|
+
| IDENTIFIER NEQ BOOLEAN { $$ = new ParserVal(new BooleanOpExp($1, $3, NEQ)); }
|
47
|
+
| BOOLEAN EQ IDENTIFIER { $$ = new ParserVal(new BooleanOpExp($1, $3, EQ)); }
|
48
|
+
| BOOLEAN NEQ IDENTIFIER { $$ = new ParserVal(new BooleanOpExp($1, $3, NEQ)); }
|
49
|
+
| IDENTIFIER EQ NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, EQ)); }
|
50
|
+
| IDENTIFIER NEQ NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, NEQ)); }
|
51
|
+
| IDENTIFIER GT NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, GT)); }
|
52
|
+
| IDENTIFIER GE NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, GE)); }
|
53
|
+
| IDENTIFIER LT NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, LT)); }
|
54
|
+
| IDENTIFIER LE NUMBER { $$ = new ParserVal(new NumberOpExp($1, $3, LE)); }
|
55
|
+
| NUMBER EQ IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, EQ)); }
|
56
|
+
| NUMBER NEQ IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, NEQ)); }
|
57
|
+
| NUMBER GT IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, GT)); }
|
58
|
+
| NUMBER GE IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, GE)); }
|
59
|
+
| NUMBER LT IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, LT)); }
|
60
|
+
| NUMBER LE IDENTIFIER { $$ = new ParserVal(new NumberOpExp($1, $3, LE)); }
|
61
|
+
| IDENTIFIER EQ STRING { $$ = new ParserVal(new StringOpExp($1, $3, EQ)); }
|
62
|
+
| IDENTIFIER NEQ STRING { $$ = new ParserVal(new StringOpExp($1, $3, NEQ)); }
|
63
|
+
| IDENTIFIER START_WITH STRING { $$ = new ParserVal(new StringOpExp($1, $3, START_WITH)); }
|
64
|
+
| IDENTIFIER END_WITH STRING { $$ = new ParserVal(new StringOpExp($1, $3, END_WITH)); }
|
65
|
+
| IDENTIFIER INCLUDE STRING { $$ = new ParserVal(new StringOpExp($1, $3, INCLUDE)); }
|
66
|
+
| STRING EQ IDENTIFIER { $$ = new ParserVal(new StringOpExp($1, $3, EQ)); }
|
67
|
+
| STRING NEQ IDENTIFIER { $$ = new ParserVal(new StringOpExp($1, $3, NEQ)); }
|
68
|
+
| STRING START_WITH IDENTIFIER { $$ = new ParserVal(new StringOpExp($1, $3, START_WITH)); }
|
69
|
+
| STRING END_WITH IDENTIFIER { $$ = new ParserVal(new StringOpExp($1, $3, END_WITH)); }
|
70
|
+
| STRING INCLUDE IDENTIFIER { $$ = new ParserVal(new StringOpExp($1, $3, INCLUDE)); }
|
71
|
+
| IDENTIFIER EQ timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, EQ)); }
|
72
|
+
| IDENTIFIER NEQ timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, NEQ)); }
|
73
|
+
| IDENTIFIER GT timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, GT)); }
|
74
|
+
| IDENTIFIER GE timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, GE)); }
|
75
|
+
| IDENTIFIER LT timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, LT)); }
|
76
|
+
| IDENTIFIER LE timestamp { $$ = new ParserVal(new TimestampOpExp($1, $3, LE)); }
|
77
|
+
| timestamp EQ IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, EQ)); }
|
78
|
+
| timestamp NEQ IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, NEQ)); }
|
79
|
+
| timestamp GT IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, GT)); }
|
80
|
+
| timestamp GE IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, GE)); }
|
81
|
+
| timestamp LT IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, LT)); }
|
82
|
+
| timestamp LE IDENTIFIER { $$ = new ParserVal(new TimestampOpExp($1, $3, LE)); }
|
83
|
+
| IDENTIFIER IS NULL { $$ = new ParserVal(new NullOpExp($1, EQ)); }
|
84
|
+
| IDENTIFIER IS NOT NULL { $$ = new ParserVal(new NullOpExp($1, NEQ)); }
|
85
|
+
| exp OR exp { $$ = new ParserVal(new LogicalOpExp($1, $3, OR)); }
|
86
|
+
| exp AND exp { $$ = new ParserVal(new LogicalOpExp($1, $3, AND)); }
|
87
|
+
| NOT exp { $$ = new ParserVal(new NegateOpExp($2)); }
|
88
|
+
| '(' exp ')' { $$ = $2; }
|
89
|
+
;
|
90
|
+
%%
|
91
|
+
|
92
|
+
protected Schema schema;
|
93
|
+
protected Yylex lexer;
|
94
|
+
protected ParserVal root;
|
95
|
+
|
96
|
+
public Parser(final Schema schema)
|
97
|
+
{
|
98
|
+
this.schema = schema;
|
99
|
+
}
|
100
|
+
|
101
|
+
public Parser(final Schema schema, boolean yydebug)
|
102
|
+
{
|
103
|
+
this.schema = schema;
|
104
|
+
this.yydebug = yydebug;
|
105
|
+
}
|
106
|
+
|
107
|
+
public ParserExp parse(String str)
|
108
|
+
{
|
109
|
+
lexer = new Yylex(str, this);
|
110
|
+
yyparse();
|
111
|
+
return ((ParserExp)(root.obj));
|
112
|
+
}
|
113
|
+
|
114
|
+
private int yylex () {
|
115
|
+
int token = -1;
|
116
|
+
try {
|
117
|
+
token = lexer.yylex(); // next token
|
118
|
+
}
|
119
|
+
catch (java.io.IOException e) {
|
120
|
+
e.printStackTrace(); // should not happen
|
121
|
+
}
|
122
|
+
return token;
|
123
|
+
}
|
124
|
+
|
125
|
+
void yyerror(String s)
|
126
|
+
{
|
127
|
+
throw new RuntimeException("yyerror: " + s);
|
128
|
+
}
|
129
|
+
|
130
|
+
/*public static void main(String args[])
|
131
|
+
{
|
132
|
+
Parser yyparser = new Parser();
|
133
|
+
ParserExp exp = yyparser.parse("boolean = true");
|
134
|
+
HashMap<String, Object> variables = new HashMap<>();
|
135
|
+
variables.put("boolean", Boolean.TRUE);
|
136
|
+
System.out.println("ans: " + exp.eval(variables));
|
137
|
+
}*/
|
@@ -0,0 +1,383 @@
|
|
1
|
+
package org.embulk.filter.row.where;
|
2
|
+
|
3
|
+
import org.embulk.EmbulkTestRuntime;
|
4
|
+
import org.embulk.config.ConfigException;
|
5
|
+
import org.embulk.spi.Page;
|
6
|
+
import org.embulk.spi.PageReader;
|
7
|
+
import org.embulk.spi.PageTestUtils;
|
8
|
+
import org.embulk.spi.Schema;
|
9
|
+
import org.embulk.spi.SchemaConfigException;
|
10
|
+
import org.embulk.spi.time.Timestamp;
|
11
|
+
|
12
|
+
import org.embulk.spi.time.TimestampParseException;
|
13
|
+
import org.jruby.embed.ScriptingContainer;
|
14
|
+
import org.junit.BeforeClass;
|
15
|
+
import org.junit.Rule;
|
16
|
+
import org.junit.Test;
|
17
|
+
import org.msgpack.value.Value;
|
18
|
+
import org.msgpack.value.ValueFactory;
|
19
|
+
|
20
|
+
import java.util.List;
|
21
|
+
|
22
|
+
import static org.embulk.spi.type.Types.BOOLEAN;
|
23
|
+
import static org.embulk.spi.type.Types.DOUBLE;
|
24
|
+
import static org.embulk.spi.type.Types.JSON;
|
25
|
+
import static org.embulk.spi.type.Types.LONG;
|
26
|
+
import static org.embulk.spi.type.Types.STRING;
|
27
|
+
import static org.embulk.spi.type.Types.TIMESTAMP;
|
28
|
+
import static org.junit.Assert.assertFalse;
|
29
|
+
import static org.junit.Assert.assertTrue;
|
30
|
+
|
31
|
+
public class TestParser
|
32
|
+
{
|
33
|
+
private static EmbulkTestRuntime runtime = new EmbulkTestRuntime(); // very slow
|
34
|
+
private static ScriptingContainer jruby = new ScriptingContainer();
|
35
|
+
|
36
|
+
private static PageReader buildPageReader(Schema schema, final Object... objects)
|
37
|
+
{
|
38
|
+
PageReader pageReader = new PageReader(schema);
|
39
|
+
List<Page> pages = PageTestUtils.buildPage(runtime.getBufferAllocator(), schema, objects);
|
40
|
+
for (Page page : pages) {
|
41
|
+
pageReader.setPage(page);
|
42
|
+
}
|
43
|
+
pageReader.nextRecord();
|
44
|
+
return pageReader;
|
45
|
+
}
|
46
|
+
|
47
|
+
private static PageReader reader;
|
48
|
+
private static Schema schema;
|
49
|
+
|
50
|
+
@BeforeClass
|
51
|
+
public static void setupBeforeClass()
|
52
|
+
{
|
53
|
+
ParserLiteral.setJRuby(jruby);
|
54
|
+
|
55
|
+
// {"k1":{"k1":"v"},"k2":{"k2":"v"}}
|
56
|
+
Value k1 = ValueFactory.newString("k1");
|
57
|
+
Value k2 = ValueFactory.newString("k2");
|
58
|
+
Value v = ValueFactory.newString("v");
|
59
|
+
Value map = ValueFactory.newMap(
|
60
|
+
k1, ValueFactory.newMap(k1, v),
|
61
|
+
k2, ValueFactory.newMap(k2, v));
|
62
|
+
|
63
|
+
schema = Schema.builder()
|
64
|
+
.add("timestamp", TIMESTAMP)
|
65
|
+
.add("string", STRING)
|
66
|
+
.add("boolean", BOOLEAN)
|
67
|
+
.add("long", LONG)
|
68
|
+
.add("double", DOUBLE)
|
69
|
+
.add("true", BOOLEAN)
|
70
|
+
.add("null", BOOLEAN)
|
71
|
+
.add("json", JSON)
|
72
|
+
.build();
|
73
|
+
|
74
|
+
reader = buildPageReader(schema,
|
75
|
+
Timestamp.ofEpochSecond(1, 500000000),
|
76
|
+
"string",
|
77
|
+
true,
|
78
|
+
1L,
|
79
|
+
1.5,
|
80
|
+
true,
|
81
|
+
null,
|
82
|
+
map
|
83
|
+
);
|
84
|
+
}
|
85
|
+
|
86
|
+
@Test
|
87
|
+
public void testIdentifierLiteral()
|
88
|
+
{
|
89
|
+
Parser parser = new Parser(schema);
|
90
|
+
ParserExp exp;
|
91
|
+
|
92
|
+
exp = parser.parse("boolean = true");
|
93
|
+
assertTrue(exp.eval(reader));
|
94
|
+
|
95
|
+
exp = parser.parse("\"true\" = true");
|
96
|
+
assertTrue(exp.eval(reader));
|
97
|
+
|
98
|
+
try {
|
99
|
+
exp = parser.parse("\"unknown\" IS NULL");
|
100
|
+
assertTrue(false);
|
101
|
+
}
|
102
|
+
catch (SchemaConfigException e) {
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
@Test
|
107
|
+
public void testBooleanOpExp()
|
108
|
+
{
|
109
|
+
Parser parser = new Parser(schema);
|
110
|
+
ParserExp exp;
|
111
|
+
|
112
|
+
exp = parser.parse("boolean = true");
|
113
|
+
assertTrue(exp.eval(reader));
|
114
|
+
exp = parser.parse("boolean = false");
|
115
|
+
assertFalse(exp.eval(reader));
|
116
|
+
|
117
|
+
exp = parser.parse("boolean != false");
|
118
|
+
assertTrue(exp.eval(reader));
|
119
|
+
exp = parser.parse("boolean != true");
|
120
|
+
assertFalse(exp.eval(reader));
|
121
|
+
|
122
|
+
exp = parser.parse("true = boolean");
|
123
|
+
assertTrue(exp.eval(reader));
|
124
|
+
|
125
|
+
try {
|
126
|
+
exp = parser.parse("timestamp = true");
|
127
|
+
assertTrue(false);
|
128
|
+
}
|
129
|
+
catch (ConfigException e) {
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
@Test
|
134
|
+
public void testNumberOpExp()
|
135
|
+
{
|
136
|
+
Parser parser = new Parser(schema);
|
137
|
+
ParserExp exp;
|
138
|
+
|
139
|
+
exp = parser.parse("double = 1.5");
|
140
|
+
assertTrue(exp.eval(reader));
|
141
|
+
exp = parser.parse("double = 1.0");
|
142
|
+
assertFalse(exp.eval(reader));
|
143
|
+
|
144
|
+
exp = parser.parse("double != 1.0");
|
145
|
+
assertTrue(exp.eval(reader));
|
146
|
+
exp = parser.parse("double != 1.5");
|
147
|
+
assertFalse(exp.eval(reader));
|
148
|
+
|
149
|
+
exp = parser.parse("double > 1.0");
|
150
|
+
assertTrue(exp.eval(reader));
|
151
|
+
exp = parser.parse("double > 1.5");
|
152
|
+
assertFalse(exp.eval(reader));
|
153
|
+
|
154
|
+
exp = parser.parse("double >= 1.5");
|
155
|
+
assertTrue(exp.eval(reader));
|
156
|
+
exp = parser.parse("double >= 2.0");
|
157
|
+
assertFalse(exp.eval(reader));
|
158
|
+
|
159
|
+
exp = parser.parse("double < 2.0");
|
160
|
+
assertTrue(exp.eval(reader));
|
161
|
+
exp = parser.parse("double < 1.5");
|
162
|
+
assertFalse(exp.eval(reader));
|
163
|
+
|
164
|
+
exp = parser.parse("double <= 1.5");
|
165
|
+
assertTrue(exp.eval(reader));
|
166
|
+
exp = parser.parse("double <= 1.0");
|
167
|
+
assertFalse(exp.eval(reader));
|
168
|
+
|
169
|
+
exp = parser.parse("1.5 = double");
|
170
|
+
assertTrue(exp.eval(reader));
|
171
|
+
|
172
|
+
try {
|
173
|
+
exp = parser.parse("timestamp = 1.5");
|
174
|
+
assertTrue(false);
|
175
|
+
}
|
176
|
+
catch (ConfigException e) {
|
177
|
+
}
|
178
|
+
}
|
179
|
+
|
180
|
+
@Test
|
181
|
+
public void testStringOpExp()
|
182
|
+
{
|
183
|
+
Parser parser = new Parser(schema);
|
184
|
+
ParserExp exp;
|
185
|
+
|
186
|
+
exp = parser.parse("string = 'string'");
|
187
|
+
assertTrue(exp.eval(reader));
|
188
|
+
exp = parser.parse("string = 'foobar'");
|
189
|
+
assertFalse(exp.eval(reader));
|
190
|
+
|
191
|
+
exp = parser.parse("string != 'foobar'");
|
192
|
+
assertTrue(exp.eval(reader));
|
193
|
+
exp = parser.parse("string != 'string'");
|
194
|
+
assertFalse(exp.eval(reader));
|
195
|
+
|
196
|
+
exp = parser.parse("string <> 'foobar'");
|
197
|
+
assertTrue(exp.eval(reader));
|
198
|
+
exp = parser.parse("string <> 'string'");
|
199
|
+
assertFalse(exp.eval(reader));
|
200
|
+
|
201
|
+
exp = parser.parse("string START_WITH 's'");
|
202
|
+
assertTrue(exp.eval(reader));
|
203
|
+
exp = parser.parse("string START_WITH 'f'");
|
204
|
+
assertFalse(exp.eval(reader));
|
205
|
+
|
206
|
+
exp = parser.parse("string END_WITH 'g'");
|
207
|
+
assertTrue(exp.eval(reader));
|
208
|
+
exp = parser.parse("string END_WITH 'r'");
|
209
|
+
assertFalse(exp.eval(reader));
|
210
|
+
|
211
|
+
exp = parser.parse("string INCLUDE 'tr'");
|
212
|
+
assertTrue(exp.eval(reader));
|
213
|
+
exp = parser.parse("string INCLUDE 'oo'");
|
214
|
+
assertFalse(exp.eval(reader));
|
215
|
+
|
216
|
+
exp = parser.parse("'string' = string");
|
217
|
+
assertTrue(exp.eval(reader));
|
218
|
+
|
219
|
+
try {
|
220
|
+
exp = parser.parse("timestamp = 'string'");
|
221
|
+
assertTrue(false);
|
222
|
+
}
|
223
|
+
catch (ConfigException e) {
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
@Test
|
228
|
+
public void testTimestampOpExpWithNumber()
|
229
|
+
{
|
230
|
+
Parser parser = new Parser(schema);
|
231
|
+
ParserExp exp;
|
232
|
+
|
233
|
+
exp = parser.parse("timestamp = TIMESTAMP 1.5");
|
234
|
+
assertTrue(exp.eval(reader));
|
235
|
+
exp = parser.parse("timestamp = TIMESTAMP 1.0");
|
236
|
+
assertFalse(exp.eval(reader));
|
237
|
+
|
238
|
+
exp = parser.parse("timestamp != TIMESTAMP 1.0");
|
239
|
+
assertTrue(exp.eval(reader));
|
240
|
+
exp = parser.parse("timestamp != TIMESTAMP 1.5");
|
241
|
+
assertFalse(exp.eval(reader));
|
242
|
+
|
243
|
+
exp = parser.parse("timestamp > TIMESTAMP 1.0");
|
244
|
+
assertTrue(exp.eval(reader));
|
245
|
+
exp = parser.parse("timestamp > TIMESTAMP 1.5");
|
246
|
+
assertFalse(exp.eval(reader));
|
247
|
+
|
248
|
+
exp = parser.parse("timestamp >= TIMESTAMP 1.5");
|
249
|
+
assertTrue(exp.eval(reader));
|
250
|
+
exp = parser.parse("timestamp >= TIMESTAMP 2.0");
|
251
|
+
assertFalse(exp.eval(reader));
|
252
|
+
|
253
|
+
exp = parser.parse("timestamp < TIMESTAMP 2.0");
|
254
|
+
assertTrue(exp.eval(reader));
|
255
|
+
exp = parser.parse("timestamp < TIMESTAMP 1.5");
|
256
|
+
assertFalse(exp.eval(reader));
|
257
|
+
|
258
|
+
exp = parser.parse("timestamp <= TIMESTAMP 1.5");
|
259
|
+
assertTrue(exp.eval(reader));
|
260
|
+
exp = parser.parse("timestamp <= TIMESTAMP 1.0");
|
261
|
+
assertFalse(exp.eval(reader));
|
262
|
+
|
263
|
+
exp = parser.parse("TIMESTAMP 1.5 = timestamp");
|
264
|
+
assertTrue(exp.eval(reader));
|
265
|
+
}
|
266
|
+
|
267
|
+
@Test
|
268
|
+
public void testTimestampOpExpWithString()
|
269
|
+
{
|
270
|
+
Parser parser = new Parser(schema);
|
271
|
+
ParserExp exp;
|
272
|
+
|
273
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 09:00:01.5 +0900'");
|
274
|
+
assertTrue(exp.eval(reader));
|
275
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 09:00:01.0 +09:00'");
|
276
|
+
assertFalse(exp.eval(reader));
|
277
|
+
|
278
|
+
exp = parser.parse("timestamp != TIMESTAMP '1970-01-01 09:00:01.0 +0900'");
|
279
|
+
assertTrue(exp.eval(reader));
|
280
|
+
exp = parser.parse("timestamp != TIMESTAMP '1970-01-01 09:00:01.5 +0900'");
|
281
|
+
assertFalse(exp.eval(reader));
|
282
|
+
|
283
|
+
exp = parser.parse("timestamp > TIMESTAMP '1970-01-01 09:00:01.0 +0900'");
|
284
|
+
assertTrue(exp.eval(reader));
|
285
|
+
exp = parser.parse("timestamp > TIMESTAMP '1970-01-01 09:00:01.5 +0900'");
|
286
|
+
assertFalse(exp.eval(reader));
|
287
|
+
|
288
|
+
exp = parser.parse("timestamp >= TIMESTAMP '1970-01-01 09:00:01.5 +09:00'");
|
289
|
+
assertTrue(exp.eval(reader));
|
290
|
+
exp = parser.parse("timestamp >= TIMESTAMP '1970-01-01 09:00:02.0 +09:00'");
|
291
|
+
assertFalse(exp.eval(reader));
|
292
|
+
|
293
|
+
exp = parser.parse("timestamp < TIMESTAMP '1970-01-01 09:00:02.0 +09:00'");
|
294
|
+
assertTrue(exp.eval(reader));
|
295
|
+
exp = parser.parse("timestamp < TIMESTAMP '1970-01-01 09:00:01.5 +09:00'");
|
296
|
+
assertFalse(exp.eval(reader));
|
297
|
+
|
298
|
+
exp = parser.parse("timestamp <= TIMESTAMP '1970-01-01 09:00:01.5 +09:00'");
|
299
|
+
assertTrue(exp.eval(reader));
|
300
|
+
exp = parser.parse("timestamp <= TIMESTAMP '1970-01-01 09:00:01.0 +09:00'");
|
301
|
+
assertFalse(exp.eval(reader));
|
302
|
+
|
303
|
+
exp = parser.parse("TIMESTAMP '1970-01-01 09:00:01.5 +09:00' = timestamp");
|
304
|
+
assertTrue(exp.eval(reader));
|
305
|
+
|
306
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 09:00:01.5 +0900'");
|
307
|
+
assertTrue(exp.eval(reader));
|
308
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 00:00:01.5'");
|
309
|
+
assertTrue(exp.eval(reader));
|
310
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 09:00:01 +09:00'");
|
311
|
+
assertFalse(exp.eval(reader));
|
312
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 00:00:01'");
|
313
|
+
assertFalse(exp.eval(reader));
|
314
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01 +09:00'");
|
315
|
+
assertFalse(exp.eval(reader));
|
316
|
+
exp = parser.parse("timestamp = TIMESTAMP '1970-01-01'");
|
317
|
+
assertFalse(exp.eval(reader));
|
318
|
+
|
319
|
+
try {
|
320
|
+
parser.parse("timestamp = TIMESTAMP '1970:01:01'");
|
321
|
+
assertTrue(false);
|
322
|
+
}
|
323
|
+
catch (TimestampParseException ex) {
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
@Test
|
328
|
+
public void testNullOpExp()
|
329
|
+
{
|
330
|
+
Parser parser = new Parser(schema);
|
331
|
+
ParserExp exp;
|
332
|
+
|
333
|
+
exp = parser.parse("null IS NULL");
|
334
|
+
assertTrue(exp.eval(reader));
|
335
|
+
exp = parser.parse("null IS NOT NULL");
|
336
|
+
assertFalse(exp.eval(reader));
|
337
|
+
|
338
|
+
exp = parser.parse("string IS NOT NULL");
|
339
|
+
assertTrue(exp.eval(reader));
|
340
|
+
exp = parser.parse("string IS NULL");
|
341
|
+
assertFalse(exp.eval(reader));
|
342
|
+
}
|
343
|
+
|
344
|
+
@Test
|
345
|
+
public void testLogicalOpExp()
|
346
|
+
{
|
347
|
+
Parser parser = new Parser(schema);
|
348
|
+
ParserExp exp;
|
349
|
+
|
350
|
+
exp = parser.parse("\"true\" = true AND \"true\" = true");
|
351
|
+
assertTrue(exp.eval(reader));
|
352
|
+
exp = parser.parse("\"true\" = true AND \"true\" = false");
|
353
|
+
assertFalse(exp.eval(reader));
|
354
|
+
|
355
|
+
exp = parser.parse("\"true\" = false OR \"true\" = true");
|
356
|
+
assertTrue(exp.eval(reader));
|
357
|
+
exp = parser.parse("\"true\" = false OR \"true\" = false");
|
358
|
+
assertFalse(exp.eval(reader));
|
359
|
+
|
360
|
+
// a AND b OR c #=> (a AND b) OR c
|
361
|
+
// a OR b AND c #=> a OR (b AND c)
|
362
|
+
exp = parser.parse("\"true\" = true OR \"true\" = false AND \"true\" = false");
|
363
|
+
assertTrue(exp.eval(reader));
|
364
|
+
exp = parser.parse("( \"true\" = true OR \"true\" = false ) AND \"true\" = false");
|
365
|
+
assertFalse(exp.eval(reader));
|
366
|
+
}
|
367
|
+
|
368
|
+
@Test
|
369
|
+
public void testNegateOpExp()
|
370
|
+
{
|
371
|
+
Parser parser = new Parser(schema);
|
372
|
+
ParserExp exp;
|
373
|
+
|
374
|
+
exp = parser.parse("NOT \"true\" = false");
|
375
|
+
assertTrue(exp.eval(reader));
|
376
|
+
exp = parser.parse("NOT ( \"true\" = false )");
|
377
|
+
assertTrue(exp.eval(reader));
|
378
|
+
|
379
|
+
// NOT a AND B #=> (NOT a) AND B
|
380
|
+
exp = parser.parse("NOT \"true\" = false AND \"true\" = true");
|
381
|
+
assertTrue(exp.eval(reader));
|
382
|
+
}
|
383
|
+
}
|