sqlancer.mysql.MySQLToStringVisitor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sqlancer Show documentation
Show all versions of sqlancer Show documentation
SQLancer finds logic bugs in Database Management Systems through automatic testing
package sqlancer.mysql;
import java.util.List;
import java.util.stream.Collectors;
import sqlancer.Randomly;
import sqlancer.common.visitor.ToStringVisitor;
import sqlancer.mysql.ast.MySQLBetweenOperation;
import sqlancer.mysql.ast.MySQLBinaryComparisonOperation;
import sqlancer.mysql.ast.MySQLBinaryLogicalOperation;
import sqlancer.mysql.ast.MySQLBinaryOperation;
import sqlancer.mysql.ast.MySQLCastOperation;
import sqlancer.mysql.ast.MySQLCollate;
import sqlancer.mysql.ast.MySQLColumnReference;
import sqlancer.mysql.ast.MySQLComputableFunction;
import sqlancer.mysql.ast.MySQLConstant;
import sqlancer.mysql.ast.MySQLExists;
import sqlancer.mysql.ast.MySQLExpression;
import sqlancer.mysql.ast.MySQLInOperation;
import sqlancer.mysql.ast.MySQLOrderByTerm;
import sqlancer.mysql.ast.MySQLOrderByTerm.MySQLOrder;
import sqlancer.mysql.ast.MySQLSelect;
import sqlancer.mysql.ast.MySQLStringExpression;
import sqlancer.mysql.ast.MySQLTableReference;
import sqlancer.mysql.ast.MySQLUnaryPostfixOperation;
public class MySQLToStringVisitor extends ToStringVisitor implements MySQLVisitor {
int ref;
@Override
public void visitSpecific(MySQLExpression expr) {
MySQLVisitor.super.visit(expr);
}
@Override
public void visit(MySQLSelect s) {
sb.append("SELECT ");
switch (s.getFromOptions()) {
case DISTINCT:
sb.append("DISTINCT ");
break;
case ALL:
sb.append(Randomly.fromOptions("ALL ", ""));
break;
case DISTINCTROW:
sb.append("DISTINCTROW ");
break;
default:
throw new AssertionError();
}
sb.append(s.getModifiers().stream().collect(Collectors.joining(" ")));
if (s.getModifiers().size() > 0) {
sb.append(" ");
}
if (s.getFetchColumns() == null) {
sb.append("*");
} else {
for (int i = 0; i < s.getFetchColumns().size(); i++) {
if (i != 0) {
sb.append(", ");
}
visit(s.getFetchColumns().get(i));
// MySQL does not allow duplicate column names
sb.append(" AS ");
sb.append("ref");
sb.append(ref++);
}
}
sb.append(" FROM ");
for (int i = 0; i < s.getFromList().size(); i++) {
if (i != 0) {
sb.append(", ");
}
visit(s.getFromList().get(i));
}
for (MySQLExpression j : s.getJoinList()) {
visit(j);
}
if (s.getWhereClause() != null) {
MySQLExpression whereClause = s.getWhereClause();
sb.append(" WHERE ");
visit(whereClause);
}
if (s.getGroupByExpressions() != null && s.getGroupByExpressions().size() > 0) {
sb.append(" ");
sb.append("GROUP BY ");
List groupBys = s.getGroupByExpressions();
for (int i = 0; i < groupBys.size(); i++) {
if (i != 0) {
sb.append(", ");
}
visit(groupBys.get(i));
}
}
if (!s.getOrderByExpressions().isEmpty()) {
sb.append(" ORDER BY ");
List orderBys = s.getOrderByExpressions();
for (int i = 0; i < orderBys.size(); i++) {
if (i != 0) {
sb.append(", ");
}
visit(s.getOrderByExpressions().get(i));
}
}
if (s.getLimitClause() != null) {
sb.append(" LIMIT ");
visit(s.getLimitClause());
}
if (s.getOffsetClause() != null) {
sb.append(" OFFSET ");
visit(s.getOffsetClause());
}
}
@Override
public void visit(MySQLConstant constant) {
sb.append(constant.getTextRepresentation());
}
@Override
public String get() {
return sb.toString();
}
@Override
public void visit(MySQLColumnReference column) {
sb.append(column.getColumn().getFullQualifiedName());
}
@Override
public void visit(MySQLUnaryPostfixOperation op) {
sb.append("(");
visit(op.getExpression());
sb.append(")");
sb.append(" IS ");
if (op.isNegated()) {
sb.append("NOT ");
}
switch (op.getOperator()) {
case IS_FALSE:
sb.append("FALSE");
break;
case IS_NULL:
if (Randomly.getBoolean()) {
sb.append("UNKNOWN");
} else {
sb.append("NULL");
}
break;
case IS_TRUE:
sb.append("TRUE");
break;
default:
throw new AssertionError(op);
}
}
@Override
public void visit(MySQLComputableFunction f) {
sb.append(f.getFunction().getName());
sb.append("(");
for (int i = 0; i < f.getArguments().length; i++) {
if (i != 0) {
sb.append(", ");
}
visit(f.getArguments()[i]);
}
sb.append(")");
}
@Override
public void visit(MySQLBinaryLogicalOperation op) {
sb.append("(");
visit(op.getLeft());
sb.append(")");
sb.append(" ");
sb.append(op.getTextRepresentation());
sb.append(" ");
sb.append("(");
visit(op.getRight());
sb.append(")");
}
@Override
public void visit(MySQLBinaryComparisonOperation op) {
sb.append("(");
visit(op.getLeft());
sb.append(") ");
sb.append(op.getOp().getTextRepresentation());
sb.append(" (");
visit(op.getRight());
sb.append(")");
}
@Override
public void visit(MySQLCastOperation op) {
sb.append("CAST(");
visit(op.getExpr());
sb.append(" AS ");
sb.append(op.getType());
sb.append(")");
}
@Override
public void visit(MySQLInOperation op) {
sb.append("(");
visit(op.getExpr());
sb.append(")");
if (!op.isTrue()) {
sb.append(" NOT");
}
sb.append(" IN ");
sb.append("(");
for (int i = 0; i < op.getListElements().size(); i++) {
if (i != 0) {
sb.append(", ");
}
visit(op.getListElements().get(i));
}
sb.append(")");
}
@Override
public void visit(MySQLBinaryOperation op) {
sb.append("(");
visit(op.getLeft());
sb.append(") ");
sb.append(op.getOp().getTextRepresentation());
sb.append(" (");
visit(op.getRight());
sb.append(")");
}
@Override
public void visit(MySQLOrderByTerm op) {
visit(op.getExpr());
sb.append(" ");
sb.append(op.getOrder() == MySQLOrder.ASC ? "ASC" : "DESC");
}
@Override
public void visit(MySQLExists op) {
sb.append(" EXISTS (");
visit(op.getExpr());
sb.append(")");
}
@Override
public void visit(MySQLStringExpression op) {
sb.append(op.getStr());
}
@Override
public void visit(MySQLBetweenOperation op) {
sb.append("(");
visit(op.getExpr());
sb.append(") BETWEEN (");
visit(op.getLeft());
sb.append(") AND (");
visit(op.getRight());
sb.append(")");
}
@Override
public void visit(MySQLTableReference ref) {
sb.append(ref.getTable().getName());
}
@Override
public void visit(MySQLCollate collate) {
sb.append("(");
visit(collate.getExpression());
sb.append(" ");
sb.append(collate.getOperatorRepresentation());
sb.append(")");
}
}