diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java index 45ef64c1bf..247354b58e 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLBinaryOperator.java @@ -92,6 +92,7 @@ public enum SQLBinaryOperator { Assignment(":=", 169), PG_And("&&", 140), + PG_ST_DISTANCE("<->", 20), ; public static int getPriority(SQLBinaryOperator operator) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index 98f4c0feab..c1d1c05628 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -690,6 +690,10 @@ public class Lexer { } else if (ch == '@') { scanChar(); token = Token.LT_MONKEYS_AT; + } else if (ch == '-' && charAt(pos + 1) == '>') { + scanChar(); + scanChar(); + token = Token.LT_SUB_GT; } else { token = Token.LT; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 8dccdf244d..bf7591378a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -115,48 +115,76 @@ public class SQLExprParser extends SQLParser { public SQLExpr bitXorRest(SQLExpr expr) { Token token = lexer.token; - if (token == Token.CARET) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.SUBGT) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.SUBGTGT) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.POUNDGT) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.POUNDGTGT) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.QUESQUES) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.QUESBAR) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, dbType); - expr = bitXorRest(expr); - } else if (token == Token.QUESAMP) { - lexer.nextToken(); - SQLExpr rightExp = primary(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, dbType); - expr = bitXorRest(expr); + switch (token) { + case CARET: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseXor, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case SUBGT:{ + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGt, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case LT_SUB_GT: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PG_ST_DISTANCE, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case SUBGTGT:{ + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.SubGtGt, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case POUNDGT: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGt, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case POUNDGTGT: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.PoundGtGt, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case QUESQUES: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesQues, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case QUESBAR: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesBar, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + case QUESAMP: { + lexer.nextToken(); + SQLExpr rightExp = primary(); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.QuesAmp, rightExp, dbType); + expr = bitXorRest(expr); + break; + } + + default: + break; } + return expr; } diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index 9a34972b2d..e0a1ef5241 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -299,7 +299,8 @@ public enum Token { DOTDOTDOT("..,"), EQ("="), GT(">"), - LT("<"), + LT("<"), + LT_SUB_GT("<->"), BANG("!"), BANGBANG("!!"), BANG_TILDE("!~"), diff --git a/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest54.java b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest54.java new file mode 100644 index 0000000000..ade73e7067 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/postgresql/select/PGSelectTest54.java @@ -0,0 +1,61 @@ +/* + * Copyright 1999-2017 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.postgresql.select; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.List; + +public class PGSelectTest54 extends TestCase { + private final String dbType = JdbcConstants.POSTGRESQL; + + public void test_0() throws Exception { + String sql = "select gid, kind, mapid, poi_id, telephone, admincode, x, y, zipcode, name, address, street, number,geom from public.v_poi order by public.v_poi.geom <-> st_point(?,?) limit 1"; + + List stmtList = SQLUtils.parseStatements(sql, dbType); + SQLStatement stmt = stmtList.get(0); + + assertEquals("SELECT gid, kind, mapid, poi_id, telephone\n" + + "\t, admincode, x, y, zipcode, name\n" + + "\t, address, street, number, geom\n" + + "FROM public.v_poi\n" + + "ORDER BY public.v_poi.geom <-> st_point(?, ?)\n" + + "LIMIT 1", SQLUtils.toPGString(stmt)); + + assertEquals("select gid, kind, mapid, poi_id, telephone\n" + + "\t, admincode, x, y, zipcode, name\n" + + "\t, address, street, number, geom\n" + + "from public.v_poi\n" + + "order by public.v_poi.geom <-> st_point(?, ?)\n" + + "limit 1", SQLUtils.toPGString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + assertEquals(1, stmtList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType); + stmt.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); + + assertEquals(14, visitor.getColumns().size()); + assertEquals(1, visitor.getTables().size()); + } +}