Skip to content

Commit e3d9403

Browse files
committed
Merge pull request NLPchina#46 from jheimbouch/master
Added support for parsing an ODBC Literal Escape Sequence. Created Unit ...
2 parents 32d6781 + 31a65e0 commit e3d9403

File tree

8 files changed

+157
-95
lines changed

8 files changed

+157
-95
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package org.durid.sql.ast.expr;
2+
3+
/**
4+
* Created by jheimbouch on 3/17/15.
5+
*/
6+
/*
7+
* Copyright 1999-2011 Alibaba Group Holding Ltd.
8+
*
9+
* Licensed under the Apache License, Version 2.0 (the "License");
10+
* you may not use this file except in compliance with the License.
11+
* You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS,
17+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
* See the License for the specific language governing permissions and
19+
* limitations under the License.
20+
*/
21+
22+
import org.durid.sql.visitor.SQLASTVisitor;
23+
24+
public class SQLOdbcExpr extends SQLCharExpr {
25+
26+
private static final long serialVersionUID = 1L;
27+
28+
public SQLOdbcExpr(){
29+
30+
}
31+
32+
public SQLOdbcExpr(String text){
33+
super(text);
34+
}
35+
36+
@Override
37+
public void output(StringBuffer buf) {
38+
if ((this.text == null) || (this.text.length() == 0)) {
39+
buf.append("NULL");
40+
} else {
41+
buf.append("{ts '");
42+
buf.append(this.text.replaceAll("'", "''"));
43+
buf.append("'}");
44+
}
45+
}
46+
47+
@Override
48+
public String getText() {
49+
StringBuilder sb = new StringBuilder();
50+
sb.append("{ts '");
51+
sb.append(this.text);
52+
sb.append("'}");
53+
return sb.toString();
54+
}
55+
56+
protected void accept0(SQLASTVisitor visitor) {
57+
visitor.visit(this);
58+
visitor.endVisit(this);
59+
}
60+
}

src/main/java/org/durid/sql/parser/SQLExprParser.java

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,36 +28,7 @@
2828
import org.durid.sql.ast.SQLOrderBy;
2929
import org.durid.sql.ast.SQLOrderingSpecification;
3030
import org.durid.sql.ast.SQLOver;
31-
import org.durid.sql.ast.expr.SQLAggregateExpr;
32-
import org.durid.sql.ast.expr.SQLAllColumnExpr;
33-
import org.durid.sql.ast.expr.SQLAllExpr;
34-
import org.durid.sql.ast.expr.SQLAnyExpr;
35-
import org.durid.sql.ast.expr.SQLBetweenExpr;
36-
import org.durid.sql.ast.expr.SQLBinaryOpExpr;
37-
import org.durid.sql.ast.expr.SQLBinaryOperator;
38-
import org.durid.sql.ast.expr.SQLCaseExpr;
39-
import org.durid.sql.ast.expr.SQLCastExpr;
40-
import org.durid.sql.ast.expr.SQLCharExpr;
41-
import org.durid.sql.ast.expr.SQLCurrentOfCursorExpr;
42-
import org.durid.sql.ast.expr.SQLDefaultExpr;
43-
import org.durid.sql.ast.expr.SQLExistsExpr;
44-
import org.durid.sql.ast.expr.SQLHexExpr;
45-
import org.durid.sql.ast.expr.SQLIdentifierExpr;
46-
import org.durid.sql.ast.expr.SQLInListExpr;
47-
import org.durid.sql.ast.expr.SQLInSubQueryExpr;
48-
import org.durid.sql.ast.expr.SQLIntegerExpr;
49-
import org.durid.sql.ast.expr.SQLListExpr;
50-
import org.durid.sql.ast.expr.SQLMethodInvokeExpr;
51-
import org.durid.sql.ast.expr.SQLNCharExpr;
52-
import org.durid.sql.ast.expr.SQLNotExpr;
53-
import org.durid.sql.ast.expr.SQLNullExpr;
54-
import org.durid.sql.ast.expr.SQLNumberExpr;
55-
import org.durid.sql.ast.expr.SQLPropertyExpr;
56-
import org.durid.sql.ast.expr.SQLQueryExpr;
57-
import org.durid.sql.ast.expr.SQLSomeExpr;
58-
import org.durid.sql.ast.expr.SQLUnaryExpr;
59-
import org.durid.sql.ast.expr.SQLUnaryOperator;
60-
import org.durid.sql.ast.expr.SQLVariantRefExpr;
31+
import org.durid.sql.ast.expr.*;
6132
import org.durid.sql.ast.statement.NotNullConstraint;
6233
import org.durid.sql.ast.statement.SQLAssignItem;
6334
import org.durid.sql.ast.statement.SQLCharactorDataType;
@@ -170,6 +141,31 @@ public SQLExpr primary() {
170141
}
171142
accept(Token.RPAREN);
172143
break;
144+
case LBRACE:
145+
lexer.nextToken();
146+
boolean foundRBrace = false;
147+
if(lexer.stringVal().equals(Token.TS.name)){
148+
String current = lexer.stringVal();
149+
do {
150+
if(current.equals(tok.RBRACE.name())){
151+
foundRBrace = true;
152+
break;
153+
}
154+
lexer.nextToken();
155+
current = lexer.token().name();
156+
}while(!foundRBrace && !current.trim().equals(""));
157+
158+
if(foundRBrace){
159+
SQLOdbcExpr sdle = new SQLOdbcExpr(lexer.stringVal());
160+
sqlExpr = sdle;
161+
accept(Token.RBRACE);
162+
}else{
163+
throw new ParserException("Error. Unable to find closing RBRACE");
164+
}
165+
}else{
166+
throw new ParserException("Error. Unable to parse ODBC Literal Timestamp");
167+
}
168+
break;
173169
case INSERT:
174170
lexer.nextToken();
175171
if (lexer.token() != Token.LPAREN) {

src/main/java/org/durid/sql/parser/Token.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,8 @@ public enum Token {
227227
PERCENT("%"),
228228
LTLT("<<"),
229229
GTGT(">>"),
230-
MONKEYS_AT("@");
230+
MONKEYS_AT("@"),
231+
TS("ts");
231232

232233
public final String name;
233234

src/main/java/org/durid/sql/visitor/SQLASTVisitor.java

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,38 +20,7 @@
2020
import org.durid.sql.ast.SQLObject;
2121
import org.durid.sql.ast.SQLOrderBy;
2222
import org.durid.sql.ast.SQLOver;
23-
import org.durid.sql.ast.expr.SQLAggregateExpr;
24-
import org.durid.sql.ast.expr.SQLAllColumnExpr;
25-
import org.durid.sql.ast.expr.SQLAllExpr;
26-
import org.durid.sql.ast.expr.SQLAnyExpr;
27-
import org.durid.sql.ast.expr.SQLBetweenExpr;
28-
import org.durid.sql.ast.expr.SQLBinaryOpExpr;
29-
import org.durid.sql.ast.expr.SQLBitStringLiteralExpr;
30-
import org.durid.sql.ast.expr.SQLCaseExpr;
31-
import org.durid.sql.ast.expr.SQLCastExpr;
32-
import org.durid.sql.ast.expr.SQLCharExpr;
33-
import org.durid.sql.ast.expr.SQLCurrentOfCursorExpr;
34-
import org.durid.sql.ast.expr.SQLDateLiteralExpr;
35-
import org.durid.sql.ast.expr.SQLDefaultExpr;
36-
import org.durid.sql.ast.expr.SQLExistsExpr;
37-
import org.durid.sql.ast.expr.SQLHexExpr;
38-
import org.durid.sql.ast.expr.SQLHexStringLiteralExpr;
39-
import org.durid.sql.ast.expr.SQLIdentifierExpr;
40-
import org.durid.sql.ast.expr.SQLInListExpr;
41-
import org.durid.sql.ast.expr.SQLInSubQueryExpr;
42-
import org.durid.sql.ast.expr.SQLIntegerExpr;
43-
import org.durid.sql.ast.expr.SQLIntervalLiteralExpr;
44-
import org.durid.sql.ast.expr.SQLListExpr;
45-
import org.durid.sql.ast.expr.SQLMethodInvokeExpr;
46-
import org.durid.sql.ast.expr.SQLNCharExpr;
47-
import org.durid.sql.ast.expr.SQLNotExpr;
48-
import org.durid.sql.ast.expr.SQLNullExpr;
49-
import org.durid.sql.ast.expr.SQLNumberExpr;
50-
import org.durid.sql.ast.expr.SQLPropertyExpr;
51-
import org.durid.sql.ast.expr.SQLQueryExpr;
52-
import org.durid.sql.ast.expr.SQLSomeExpr;
53-
import org.durid.sql.ast.expr.SQLUnaryExpr;
54-
import org.durid.sql.ast.expr.SQLVariantRefExpr;
23+
import org.durid.sql.ast.expr.*;
5524
import org.durid.sql.ast.statement.NotNullConstraint;
5625
import org.durid.sql.ast.statement.SQLAlterTableAddColumn;
5726
import org.durid.sql.ast.statement.SQLAlterTableAddPrimaryKey;
@@ -98,6 +67,8 @@ public interface SQLASTVisitor {
9867

9968
void endVisit(SQLBinaryOpExpr x);
10069

70+
void endVisit(SQLOdbcExpr x);
71+
10172
void endVisit(SQLCaseExpr x);
10273

10374
void endVisit(SQLCaseExpr.Item x);
@@ -138,6 +109,8 @@ public interface SQLASTVisitor {
138109

139110
boolean visit(SQLBinaryOpExpr x);
140111

112+
boolean visit(SQLOdbcExpr x);
113+
141114
boolean visit(SQLCaseExpr x);
142115

143116
boolean visit(SQLCaseExpr.Item x);

src/main/java/org/durid/sql/visitor/SQLASTVisitorAdapter.java

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,38 +20,7 @@
2020
import org.durid.sql.ast.SQLObject;
2121
import org.durid.sql.ast.SQLOrderBy;
2222
import org.durid.sql.ast.SQLOver;
23-
import org.durid.sql.ast.expr.SQLAggregateExpr;
24-
import org.durid.sql.ast.expr.SQLAllColumnExpr;
25-
import org.durid.sql.ast.expr.SQLAllExpr;
26-
import org.durid.sql.ast.expr.SQLAnyExpr;
27-
import org.durid.sql.ast.expr.SQLBetweenExpr;
28-
import org.durid.sql.ast.expr.SQLBinaryOpExpr;
29-
import org.durid.sql.ast.expr.SQLBitStringLiteralExpr;
30-
import org.durid.sql.ast.expr.SQLCaseExpr;
31-
import org.durid.sql.ast.expr.SQLCastExpr;
32-
import org.durid.sql.ast.expr.SQLCharExpr;
33-
import org.durid.sql.ast.expr.SQLCurrentOfCursorExpr;
34-
import org.durid.sql.ast.expr.SQLDateLiteralExpr;
35-
import org.durid.sql.ast.expr.SQLDefaultExpr;
36-
import org.durid.sql.ast.expr.SQLExistsExpr;
37-
import org.durid.sql.ast.expr.SQLHexExpr;
38-
import org.durid.sql.ast.expr.SQLHexStringLiteralExpr;
39-
import org.durid.sql.ast.expr.SQLIdentifierExpr;
40-
import org.durid.sql.ast.expr.SQLInListExpr;
41-
import org.durid.sql.ast.expr.SQLInSubQueryExpr;
42-
import org.durid.sql.ast.expr.SQLIntegerExpr;
43-
import org.durid.sql.ast.expr.SQLIntervalLiteralExpr;
44-
import org.durid.sql.ast.expr.SQLListExpr;
45-
import org.durid.sql.ast.expr.SQLMethodInvokeExpr;
46-
import org.durid.sql.ast.expr.SQLNCharExpr;
47-
import org.durid.sql.ast.expr.SQLNotExpr;
48-
import org.durid.sql.ast.expr.SQLNullExpr;
49-
import org.durid.sql.ast.expr.SQLNumberExpr;
50-
import org.durid.sql.ast.expr.SQLPropertyExpr;
51-
import org.durid.sql.ast.expr.SQLQueryExpr;
52-
import org.durid.sql.ast.expr.SQLSomeExpr;
53-
import org.durid.sql.ast.expr.SQLUnaryExpr;
54-
import org.durid.sql.ast.expr.SQLVariantRefExpr;
23+
import org.durid.sql.ast.expr.*;
5524
import org.durid.sql.ast.statement.NotNullConstraint;
5625
import org.durid.sql.ast.statement.SQLAlterTableAddColumn;
5726
import org.durid.sql.ast.statement.SQLAlterTableAddPrimaryKey;
@@ -102,6 +71,9 @@ public void endVisit(SQLBetweenExpr x) {
10271
public void endVisit(SQLBinaryOpExpr x) {
10372
}
10473

74+
public void endVisit(SQLOdbcExpr x) {
75+
}
76+
10577
public void endVisit(SQLCaseExpr x) {
10678
}
10779

@@ -165,6 +137,8 @@ public boolean visit(SQLBinaryOpExpr x) {
165137
return true;
166138
}
167139

140+
public boolean visit(SQLOdbcExpr x) { return false; }
141+
168142
public boolean visit(SQLCaseExpr x) {
169143
return true;
170144
}

src/test/java/org/nlpcn/es4sql/MainTestSuite.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse;
66
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
77
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
8+
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
89
import org.elasticsearch.action.bulk.BulkRequestBuilder;
910
import org.elasticsearch.action.bulk.BulkResponse;
1011
import org.elasticsearch.action.delete.DeleteRequestBuilder;
@@ -52,6 +53,10 @@ public static void setUp() throws Exception {
5253
loadBulk("src/test/resources/phrases.json");
5354
loadBulk("src/test/resources/online.json");
5455

56+
prepareOdbcIndex();
57+
loadBulk("src/test/resources/odbc-date-formats.json");
58+
59+
5560

5661
searchDao = new SearchDao(client);
5762
System.out.println("Finished the setup process...");
@@ -114,6 +119,23 @@ public static void loadBulk(String jsonPath) throws Exception {
114119
}
115120
}
116121

122+
public static void prepareOdbcIndex(){
123+
String dataMapping = "{\n" +
124+
"\t\"odbc\" :{\n" +
125+
"\t\t\"properties\":{\n" +
126+
"\t\t\t\"insert_time\":{\n" +
127+
"\t\t\t\t\"type\":\"date\",\n" +
128+
"\t\t\t\t\"format\": \"{'ts' ''yyyy-MM-dd HH:mm:ss.SSS''}\"\n" +
129+
"\t\t\t},\n" +
130+
"\t\t\t\"docCount\":{\n" +
131+
"\t\t\t\t\"type\":\"string\"\n" +
132+
"\t\t\t}\n" +
133+
"\t\t}\n" +
134+
"\t}\n" +
135+
"}";
136+
137+
client.admin().indices().preparePutMapping(TEST_INDEX).setType("odbc").setSource(dataMapping).execute().actionGet();
138+
}
117139

118140
public static SearchDao getSearchDao() {
119141
return searchDao;

src/test/java/org/nlpcn/es4sql/QueryTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,22 @@ public void dateSearch() throws IOException, SqlParseException, SQLFeatureNotSup
290290
}
291291
}
292292

293+
@Test
294+
public void dateSearchBraces() throws IOException, SqlParseException, SQLFeatureNotSupportedException, ParseException {
295+
DateTimeFormatter formatter = DateTimeFormat.forPattern(DATE_FORMAT);
296+
DateTime dateToCompare = new DateTime(2015, 1, 15, 0, 0, 0);
297+
298+
SearchHits response = query(String.format("SELECT insert_time FROM %s/odbc WHERE insert_time < {ts '2015-03-15 00:00:00.000'}", TEST_INDEX));
299+
SearchHit[] hits = response.getHits();
300+
for(SearchHit hit : hits) {
301+
Map<String, Object> source = hit.getSource();
302+
DateTime insertTime = formatter.parseDateTime((String) source.get("insert_time"));
303+
304+
String errorMessage = String.format("insert_time must be smaller then 2015-03-15. found: %s", insertTime);
305+
Assert.assertTrue(errorMessage, insertTime.isBefore(dateToCompare));
306+
}
307+
}
308+
293309

294310
@Test
295311
public void dateBetweenSearch() throws IOException, SqlParseException, SQLFeatureNotSupportedException {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{"index":{"_type": "odbc"}}
2+
{"insert_time":"{ts '2015-03-16 13:27:33.953'}", "docCount":"1"}
3+
{"index":{"_type": "odbc"}}
4+
{"insert_time":"{ts '2015-03-15 13:27:33.953'}", "docCount":"2"}
5+
{"index":{"_type": "odbc"}}
6+
{"insert_time":"{ts '2015-03-14 13:27:33.953'}", "docCount":"3"}
7+
{"index":{"_type": "odbc"}}
8+
{"insert_time":"{ts '2015-03-13 13:27:33.954'}", "docCount":"4"}
9+
{"index":{"_type": "odbc"}}
10+
{"insert_time":"{ts '2015-03-12 13:27:33.954'}", "docCount":"5"}
11+
{"index":{"_type": "odbc"}}
12+
{"insert_time":"{ts '2015-03-11 13:27:33.955'}", "docCount":"6"}
13+
{"index":{"_type": "odbc"}}
14+
{"insert_time":"{ts '2015-03-10 13:27:33.955'}", "docCount":"7"}
15+
{"index":{"_type": "odbc"}}
16+
{"insert_time":"{ts '2015-03-09 13:27:33.955'}", "docCount":"8"}
17+
{"index":{"_type": "odbc"}}
18+
{"insert_time":"{ts '2015-03-08 13:27:33.956'}", "docCount":"9"}
19+
{"index":{"_type": "odbc"}}
20+
{"insert_time":"{ts '2015-03-07 13:27:33.956'}", "docCount":"10"}

0 commit comments

Comments
 (0)