private static boolean mergeEqual(SQLExpr a, SQLExpr b) { if (!(a instanceof SQLBinaryOpExpr)) { return false; } if (!(b instanceof SQLBinaryOpExpr)) { return false; } SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a; SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b; if (binaryA.getOperator() != SQLBinaryOperator.Equality) { return false; } if (binaryB.getOperator() != SQLBinaryOperator.Equality) { return false; } if (!(binaryA.getRight() instanceof SQLLiteralExpr || binaryA.getRight() instanceof SQLVariantRefExpr)) { return false; } if (!(binaryB.getRight() instanceof SQLLiteralExpr || binaryB.getRight() instanceof SQLVariantRefExpr)) { return false; } return binaryA.getLeft().toString().equals(binaryB.getLeft().toString()); }
/** * 目前只支持这个操作 单条insert(非批量) * * @param schema * @param rrs * @param partitionColumn * @param tableName * @param insertStmt * @throws SQLNonTransientException */ private void parserSingleInsert( SchemaConfig schema, RouteResultset rrs, String partitionColumn, String tableName, MySqlInsertStatement insertStmt) throws SQLNonTransientException { boolean isFound = false; // 将分片的键 作为 路由计算单元 for (int i = 0; i < insertStmt.getColumns().size(); i++) { if (partitionColumn.equalsIgnoreCase( StringUtil.removeBackquote(insertStmt.getColumns().get(i).toString()))) { // 找到分片字段 isFound = true; String column = StringUtil.removeBackquote(insertStmt.getColumns().get(i).toString()); String value = StringUtil.removeBackquote(insertStmt.getValues().getValues().get(i).toString()); RouteCalculateUnit routeCalculateUnit = new RouteCalculateUnit(); routeCalculateUnit.addShardingExpr(tableName, column, value); ctx.addRouteCalculateUnit(routeCalculateUnit); // mycat是单分片键,找到了就返回 break; } } if (!isFound) { // 分片表的 String msg = "bad insert sql (sharding column:" + partitionColumn + " not provided," + insertStmt; logger.warn(msg); throw new SQLNonTransientException(msg); } // 这种语句不应该支持 // insert into .... on duplicateKey // such as : INSERT INTO TABLEName (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE // b=VALUES(b); // INSERT INTO TABLEName (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; // du plicate 处理!! if (insertStmt.getDuplicateKeyUpdate() != null) { List<SQLExpr> updateList = insertStmt.getDuplicateKeyUpdate(); for (SQLExpr expr : updateList) { SQLBinaryOpExpr opExpr = (SQLBinaryOpExpr) expr; String column = StringUtil.removeBackquote(opExpr.getLeft().toString().toUpperCase()); if (column.equals(partitionColumn)) { String msg = "partion key can't be updated: " + tableName + " -> " + partitionColumn; logger.warn(msg); throw new SQLNonTransientException(msg); } } } }
public void test_binary() throws Exception { SQLExprParser exprParser = new SQLExprParser("AGE > 5"); SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) exprParser.expr(); Assert.assertEquals(SQLBinaryOperator.GreaterThan, binaryOpExpr.getOperator()); SQLIdentifierExpr left = (SQLIdentifierExpr) binaryOpExpr.getLeft(); SQLIntegerExpr right = (SQLIntegerExpr) binaryOpExpr.getRight(); Assert.assertEquals("AGE", left.getName()); Assert.assertEquals(5, right.getNumber().intValue()); }
private static boolean isLiteralExpr(SQLExpr expr) { if (expr instanceof SQLLiteralExpr) { return true; } if (expr instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr binary = (SQLBinaryOpExpr) expr; return isLiteralExpr(binary.getLeft()) && isLiteralExpr(binary.getRight()); } return false; }
public static boolean visit(ParameterizedVisitor v, SQLNullExpr x) { SQLObject parent = x.getParent(); if (parent instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) parent; if (binaryOpExpr.getOperator() == SQLBinaryOperator.IsNot || binaryOpExpr.getOperator() == SQLBinaryOperator.Is) { v.print("NULL"); return false; } } v.print('?'); v.incrementReplaceCunt(); return false; }
public static void exportParameter(final List<Object> parameters, SQLBinaryOpExpr x) { if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr && x.getOperator().isRelational()) { return; } { SQLExpr leftResult = ExportParameterVisitorUtils.exportParameter(parameters, x.getLeft()); if (leftResult != x.getLeft()) { x.setLeft(leftResult); } } { SQLExpr rightResult = exportParameter(parameters, x.getRight()); if (rightResult != x.getRight()) { x.setRight(rightResult); } } }
private void parseTableSourceQueryTableExpr(OracleSelectTableReference tableReference) { tableReference.setExpr(this.createExprParser().expr()); if (identifierEquals("SAMPLE")) { lexer.nextToken(); SampleClause sample = new SampleClause(); if (identifierEquals("BLOCK")) { sample.setBlock(true); } accept(Token.LPAREN); if (lexer.token() != Token.LITERAL_INT) { throw new ParserException("syntax error : " + lexer.token()); } sample.setPercent(lexer.integerValue().intValue()); lexer.nextToken(); accept(Token.RPAREN); if (identifierEquals("SEED")) { lexer.nextToken(); accept(Token.LPAREN); sample.setSeedValue(expr()); accept(Token.RPAREN); } tableReference.setSampleClause(sample); } if (identifierEquals("PARTITION")) { lexer.nextToken(); PartitionExtensionClause partition = new PartitionExtensionClause(); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); partition.setPartition(createExprParser().name()); accept(Token.RPAREN); } else { accept(Token.FOR); accept(Token.LPAREN); createExprParser().names(partition.getFor()); accept(Token.RPAREN); } tableReference.setPartition(partition); } if (identifierEquals("SUBPARTITION")) { lexer.nextToken(); PartitionExtensionClause partition = new PartitionExtensionClause(); partition.setSubPartition(true); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); partition.setPartition(createExprParser().name()); accept(Token.RPAREN); } else { accept(Token.FOR); accept(Token.LPAREN); createExprParser().names(partition.getFor()); accept(Token.RPAREN); } tableReference.setPartition(partition); } if (lexer.token() == Token.AS) { lexer.nextToken(); if (identifierEquals("OF")) { lexer.nextToken(); AsOfFlashbackQueryClause clause = new AsOfFlashbackQueryClause(); if (identifierEquals("SCN")) { clause.setType(AsOfFlashbackQueryClause.Type.SCN); lexer.nextToken(); } else { accept(Token.TIMESTAMP); clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP); } clause.setExpr(createExprParser().primary()); tableReference.setFlashback(clause); } else { throw new SQLParseException("TODO"); } } else if (identifierEquals("VERSIONS")) { lexer.nextToken(); if (lexer.token() == Token.BETWEEN) { lexer.nextToken(); VersionsFlashbackQueryClause clause = new VersionsFlashbackQueryClause(); if (identifierEquals("SCN")) { clause.setType(AsOfFlashbackQueryClause.Type.SCN); lexer.nextToken(); } else { accept(Token.TIMESTAMP); clause.setType(AsOfFlashbackQueryClause.Type.TIMESTAMP); } SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) createExprParser().expr(); if (binaryExpr.getOperator() != SQLBinaryOperator.BooleanAnd) { throw new SQLParseException("syntax error : " + binaryExpr.getOperator()); } clause.setBegin(binaryExpr.getLeft()); clause.setEnd(binaryExpr.getRight()); tableReference.setFlashback(clause); } else { throw new SQLParseException("TODO"); } } }
public static SQLBinaryOpExpr merge(ParameterizedVisitor v, SQLBinaryOpExpr x) { SQLExpr left = x.getLeft(); SQLExpr right = x.getRight(); SQLObject parent = x.getParent(); if (left instanceof SQLLiteralExpr && right instanceof SQLLiteralExpr) { if (x.getOperator() == SQLBinaryOperator.Equality // || x.getOperator() == SQLBinaryOperator.NotEqual) { if ((left instanceof SQLIntegerExpr) && (right instanceof SQLIntegerExpr)) { if (((SQLIntegerExpr) left).getNumber().intValue() < 100) { left.putAttribute(ATTR_PARAMS_SKIP, true); } if (((SQLIntegerExpr) right).getNumber().intValue() < 100) { right.putAttribute(ATTR_PARAMS_SKIP, true); } } else { left.putAttribute(ATTR_PARAMS_SKIP, true); right.putAttribute(ATTR_PARAMS_SKIP, true); } } return x; } for (; ; ) { if (x.getRight() instanceof SQLBinaryOpExpr) { if (x.getLeft() instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.getLeft(); if (leftBinaryExpr.getRight().equals(x.getRight())) { x = leftBinaryExpr; v.incrementReplaceCunt(); continue; } } SQLExpr mergedRight = merge(v, (SQLBinaryOpExpr) x.getRight()); if (mergedRight != x.getRight()) { x = new SQLBinaryOpExpr(x.getLeft(), x.getOperator(), mergedRight); v.incrementReplaceCunt(); } x.setParent(parent); } break; } if (x.getLeft() instanceof SQLBinaryOpExpr) { SQLExpr mergedLeft = merge(v, (SQLBinaryOpExpr) x.getLeft()); if (mergedLeft != x.getLeft()) { x = new SQLBinaryOpExpr(mergedLeft, x.getOperator(), x.getRight()); v.incrementReplaceCunt(); } x.setParent(parent); } // ID = ? OR ID = ? => ID = ? if (x.getOperator() == SQLBinaryOperator.BooleanOr) { if ((left instanceof SQLBinaryOpExpr) && (right instanceof SQLBinaryOpExpr)) { SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) x.getLeft(); SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.getRight(); if (mergeEqual(leftBinary, rightBinary)) { v.incrementReplaceCunt(); return leftBinary; } if (isLiteralExpr(leftBinary.getLeft()) // && leftBinary.getOperator() == SQLBinaryOperator.BooleanOr) { if (mergeEqual(leftBinary.getRight(), right)) { v.incrementReplaceCunt(); return leftBinary; } } } } return x; }
public boolean visit(SQLBinaryOpExpr x) { x.getLeft().setParent(x); x.getRight().setParent(x); switch (x.getOperator()) { case Equality: case NotEqual: case GreaterThan: case GreaterThanOrEqual: case LessThan: case LessThanOrEqual: case LessThanOrEqualOrGreaterThan: case Like: case NotLike: case Is: case IsNot: handleCondition(x.getLeft(), x.getOperator().name, x.getRight()); handleCondition(x.getRight(), x.getOperator().name, x.getLeft()); handleRelationship(x.getLeft(), x.getOperator().name, x.getRight()); break; default: break; } return true; }
public static boolean visit(SQLEvalVisitor visitor, SQLBinaryOpExpr x) { SQLExpr left = x.getLeft(); SQLExpr right = x.getRight(); left.accept(visitor); if (!left.getAttributes().containsKey(EVAL_VALUE)) { return false; } right.accept(visitor); if (!right.getAttributes().containsKey(EVAL_VALUE)) { return false; } Object value = null; switch (x.getOperator()) { case Add: value = add(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case Subtract: value = sub(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case Multiply: value = multi(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case Divide: value = div(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case GreaterThan: value = gt(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case GreaterThanOrEqual: value = gteq(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case LessThan: value = lt(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case LessThanOrEqual: value = lteq(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case Is: value = eq(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case IsNot: value = !eq(left.getAttribute(EVAL_VALUE), right.getAttributes().get(EVAL_VALUE)); x.putAttribute(EVAL_VALUE, value); break; case RegExp: case RLike: { String pattern = _string(right.getAttributes().get(EVAL_VALUE)); String input = _string(left.getAttributes().get(EVAL_VALUE)); boolean matchResult = Pattern.matches(pattern, input); x.putAttribute(EVAL_VALUE, matchResult); } break; case NotRegExp: case NotRLike: { String pattern = _string(right.getAttributes().get(EVAL_VALUE)); String input = _string(left.getAttributes().get(EVAL_VALUE)); boolean matchResult = !Pattern.matches(pattern, input); x.putAttribute(EVAL_VALUE, matchResult); } break; default: break; } return false; }
public void parseStatementList(List<SQLStatement> statementList, int max) { for (; ; ) { if (max != -1) { if (statementList.size() >= max) { return; } } if (lexer.token() == Token.EOF) { return; } if (lexer.token() == Token.END) { return; } if (lexer.token() == Token.ELSE) { return; } if (lexer.token() == (Token.SEMI)) { lexer.nextToken(); continue; } if (lexer.token() == (Token.SELECT)) { SQLSelectStatement stmt = new SQLSelectStatement( new OracleSelectParser(this.exprParser).select(), JdbcConstants.ORACLE); statementList.add(stmt); continue; } if (lexer.token() == (Token.UPDATE)) { statementList.add(parseUpdateStatement()); continue; } if (lexer.token() == (Token.CREATE)) { statementList.add(parseCreate()); continue; } if (lexer.token() == Token.INSERT) { statementList.add(parseInsert()); continue; } if (lexer.token() == (Token.DELETE)) { statementList.add(parseDeleteStatement()); continue; } if (lexer.token() == (Token.SLASH)) { lexer.nextToken(); statementList.add(new OraclePLSQLCommitStatement()); continue; } if (lexer.token() == Token.ALTER) { statementList.add(parserAlter()); continue; } if (lexer.token() == Token.WITH) { statementList.add(new SQLSelectStatement(new OracleSelectParser(this.exprParser).select())); continue; } if (lexer.token() == Token.LBRACE || identifierEquals("CALL")) { statementList.add(this.parseCall()); continue; } if (lexer.token() == Token.MERGE) { statementList.add(this.parseMerge()); continue; } if (lexer.token() == Token.BEGIN) { statementList.add(this.parseBlock()); continue; } if (lexer.token() == Token.DECLARE) { statementList.add(this.parseBlock()); continue; } if (lexer.token() == Token.LOCK) { statementList.add(this.parseLock()); continue; } if (lexer.token() == Token.TRUNCATE) { statementList.add(this.parseTruncate()); continue; } if (lexer.token() == Token.VARIANT) { SQLExpr variant = this.exprParser.primary(); if (variant instanceof SQLBinaryOpExpr) { SQLBinaryOpExpr binaryOpExpr = (SQLBinaryOpExpr) variant; if (binaryOpExpr.getOperator() == SQLBinaryOperator.Assignment) { SQLSetStatement stmt = new SQLSetStatement(binaryOpExpr.getLeft(), binaryOpExpr.getRight(), getDbType()); statementList.add(stmt); continue; } } accept(Token.COLONEQ); SQLExpr value = this.exprParser.expr(); SQLSetStatement stmt = new SQLSetStatement(variant, value, getDbType()); statementList.add(stmt); continue; } if (lexer.token() == Token.EXCEPTION) { statementList.add(this.parseException()); continue; } if (identifierEquals("EXIT")) { lexer.nextToken(); OracleExitStatement stmt = new OracleExitStatement(); if (lexer.token() == Token.WHEN) { lexer.nextToken(); stmt.setWhen(this.exprParser.expr()); } statementList.add(stmt); continue; } if (lexer.token() == Token.FETCH || identifierEquals("FETCH")) { SQLStatement stmt = parseFetch(); statementList.add(stmt); continue; } if (identifierEquals("ROLLBACK")) { SQLRollbackStatement stmt = parseRollback(); statementList.add(stmt); continue; } if (lexer.token() == Token.EXPLAIN) { statementList.add(this.parseExplain()); continue; } if (lexer.token() == Token.IDENTIFIER) { SQLExpr expr = exprParser.expr(); OracleExprStatement stmt = new OracleExprStatement(expr); statementList.add(stmt); continue; } if (lexer.token() == Token.LPAREN) { char ch = lexer.current(); int bp = lexer.bp(); lexer.nextToken(); if (lexer.token() == Token.SELECT) { lexer.reset(bp, ch, Token.LPAREN); statementList.add(this.parseSelect()); continue; } else { throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } } if (lexer.token() == Token.SET) { statementList.add(this.parseSet()); continue; } if (lexer.token() == Token.GRANT) { statementList.add(this.parseGrant()); continue; } if (lexer.token() == Token.REVOKE) { statementList.add(this.parseRevoke()); continue; } if (lexer.token() == Token.COMMENT) { statementList.add(this.parseComment()); continue; } if (lexer.token() == Token.FOR) { statementList.add(this.parseFor()); continue; } if (lexer.token() == Token.LOOP) { statementList.add(this.parseLoop()); continue; } if (lexer.token() == Token.IF) { statementList.add(this.parseIf()); continue; } if (lexer.token() == Token.GOTO) { lexer.nextToken(); SQLName label = this.exprParser.name(); OracleGotoStatement stmt = new OracleGotoStatement(label); statementList.add(stmt); continue; } if (lexer.token() == Token.COMMIT) { lexer.nextToken(); if (identifierEquals("WORK")) { lexer.nextToken(); } OracleCommitStatement stmt = new OracleCommitStatement(); if (identifierEquals("WRITE")) { stmt.setWrite(true); lexer.nextToken(); for (; ; ) { if (lexer.token() == Token.WAIT) { lexer.nextToken(); stmt.setWait(Boolean.TRUE); continue; } else if (lexer.token() == Token.NOWAIT) { lexer.nextToken(); stmt.setWait(Boolean.FALSE); continue; } else if (lexer.token() == Token.IMMEDIATE) { lexer.nextToken(); stmt.setImmediate(Boolean.TRUE); continue; } else if (identifierEquals("BATCH")) { lexer.nextToken(); stmt.setImmediate(Boolean.FALSE); continue; } break; } } statementList.add(stmt); continue; } if (lexer.token() == Token.SAVEPOINT) { lexer.nextToken(); OracleSavePointStatement stmt = new OracleSavePointStatement(); if (lexer.token() == Token.TO) { lexer.nextToken(); stmt.setTo(this.exprParser.name()); } statementList.add(stmt); continue; } if (lexer.token() == Token.LTLT) { lexer.nextToken(); SQLName label = this.exprParser.name(); OracleLabelStatement stmt = new OracleLabelStatement(label); accept(Token.GTGT); statementList.add(stmt); continue; } if (lexer.token() == Token.DROP) { lexer.nextToken(); if (lexer.token() == Token.TABLE) { SQLDropTableStatement stmt = parseDropTable(false); statementList.add(stmt); continue; } boolean isPublic = false; if (identifierEquals("PUBLIC")) { lexer.nextToken(); isPublic = true; } if (lexer.token() == Token.DATABASE) { lexer.nextToken(); if (identifierEquals("LINK")) { lexer.nextToken(); OracleDropDbLinkStatement stmt = new OracleDropDbLinkStatement(); if (isPublic) { stmt.setPublic(isPublic); } stmt.setName(this.exprParser.name()); statementList.add(stmt); continue; } } if (lexer.token() == Token.INDEX) { SQLStatement stmt = parseDropIndex(); statementList.add(stmt); continue; } if (lexer.token() == Token.VIEW) { SQLStatement stmt = parseDropView(false); statementList.add(stmt); continue; } if (lexer.token() == Token.SEQUENCE) { SQLDropSequenceStatement stmt = parseDropSequece(false); statementList.add(stmt); continue; } if (lexer.token() == Token.TRIGGER) { SQLDropTriggerStatement stmt = parseDropTrigger(false); statementList.add(stmt); continue; } if (lexer.token() == Token.USER) { SQLDropUserStatement stmt = parseDropUser(); statementList.add(stmt); continue; } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } if (lexer.token() == Token.NULL) { lexer.nextToken(); OracleExprStatement stmt = new OracleExprStatement(new SQLNullExpr()); statementList.add(stmt); continue; } if (lexer.token() == Token.OPEN) { SQLStatement stmt = this.parseOpen(); statementList.add(stmt); continue; } throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal()); } }