package com.github.vincentrussell.query.mongodb.sql.converter.holder.from; import com.github.vincentrussell.query.mongodb.sql.converter.FieldType; import com.github.vincentrussell.query.mongodb.sql.converter.SQLCommandType; import com.github.vincentrussell.query.mongodb.sql.converter.holder.AliasHolder; import com.github.vincentrussell.query.mongodb.sql.converter.util.SqlUtils; import com.github.vincentrussell.query.mongodb.sql.converter.visitor.ExpVisitorEraseAliasTableBaseBuilder; import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.parser.CCJSqlParser; import net.sf.jsqlparser.parser.ParseException; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.delete.Delete; import net.sf.jsqlparser.statement.select.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class SQLCommandInfoHolder implements SQLInfoHolder{ private final SQLCommandType sqlCommandType; private final boolean isDistinct; private final boolean isCountAll; private final boolean isTotalGroup; private final FromHolder from; private final long limit; private final long offset; private final Expression whereClause; private final List<SelectItem> selectItems; private final List<Join> joins; private final List<String> groupBys; private final List<OrderByElement> orderByElements; private final AliasHolder aliasHolder; private final Expression havingClause; public SQLCommandInfoHolder(SQLCommandType sqlCommandType, Expression whereClause, boolean isDistinct, boolean isCountAll, boolean isTotalGroup, FromHolder from, long limit, long offset, List<SelectItem> selectItems, List<Join> joins, List<String> groupBys, List<OrderByElement> orderByElements, AliasHolder aliasHolder, Expression havingClause) { this.sqlCommandType = sqlCommandType; this.whereClause = whereClause; this.isDistinct = isDistinct; this.isCountAll = isCountAll; this.isTotalGroup = isTotalGroup; this.from = from; this.limit = limit; this.offset = offset; this.selectItems = selectItems; this.joins = joins; this.groupBys = groupBys; this.havingClause = havingClause; this.orderByElements = orderByElements; this.aliasHolder = aliasHolder; } @Override public String getBaseTableName() throws ParseException { return from.getBaseFromTableName(); } public boolean isDistinct() { return isDistinct; } public boolean isCountAll() { return isCountAll; } public boolean isTotalGroup() { return isTotalGroup; } public String getTable() throws ParseException { return from.getBaseFromTableName(); } public FromHolder getFromHolder() { return this.from; } public long getLimit() { return limit; } public long getOffset() { return offset; } public Expression getWhereClause() { return whereClause; } public List<SelectItem> getSelectItems() { return selectItems; } public List<Join> getJoins() { return joins; } public List<String> getGoupBys() { return groupBys; } public Expression getHavingClause() { return havingClause; } public List<OrderByElement> getOrderByElements() { return orderByElements; } public SQLCommandType getSqlCommandType() { return sqlCommandType; } public AliasHolder getAliasHolder() { return aliasHolder; } public static class Builder { private final FieldType defaultFieldType; private final Map<String, FieldType> fieldNameToFieldTypeMapping; private SQLCommandType sqlCommandType; private Expression whereClause; private boolean isDistinct = false; private boolean isCountAll = false; private boolean isTotalGroup = false; private FromHolder from; private long limit = -1; private long offset = -1; private List<SelectItem> selectItems = new ArrayList<>(); private List<Join> joins = new ArrayList<>(); private List<String> groupBys = new ArrayList<>(); private Expression havingClause; private List<OrderByElement> orderByElements1 = new ArrayList<>(); private AliasHolder aliasHolder; private Builder(FieldType defaultFieldType, Map<String, FieldType> fieldNameToFieldTypeMapping){ this.defaultFieldType = defaultFieldType; this.fieldNameToFieldTypeMapping = fieldNameToFieldTypeMapping; } private FromHolder generateFromHolder(FromHolder tholder, FromItem fromItem, List<Join> ljoin) throws ParseException, com.github.vincentrussell.query.mongodb.sql.converter.ParseException { Alias alias = fromItem.getAlias(); tholder.addFrom(fromItem,(alias != null ? alias.getName() : null)); if(ljoin != null) { for (Join j : ljoin) { SqlUtils.updateJoinType(j); if(j.isInner() || j.isLeft()) { tholder = generateFromHolder(tholder,j.getRightItem(),null); } else{ throw new ParseException("Join type not suported"); } } } return tholder; } public Builder setJSqlParser(CCJSqlParser jSqlParser) throws com.github.vincentrussell.query.mongodb.sql.converter.ParseException, ParseException { final Statement statement = jSqlParser.Statement(); return setStatement(statement); } public Builder setStatement(Statement statement) throws com.github.vincentrussell.query.mongodb.sql.converter.ParseException, ParseException { if (Select.class.isAssignableFrom(statement.getClass())) { sqlCommandType = SQLCommandType.SELECT; SelectBody selectBody = ((Select) statement).getSelectBody(); if (SetOperationList.class.isInstance(selectBody)) { SetOperationList setOperationList = (SetOperationList)selectBody; if (setOperationList.getSelects() != null && setOperationList.getSelects().size() == 1 && PlainSelect.class.isInstance(setOperationList.getSelects().get(0))) { return setPlainSelect((PlainSelect) setOperationList.getSelects().get(0)); } } else if (PlainSelect.class.isInstance(selectBody)) { return setPlainSelect((PlainSelect) selectBody); } throw new ParseException("No supported sentence"); } else if (Delete.class.isAssignableFrom(statement.getClass())) { sqlCommandType = SQLCommandType.DELETE; Delete delete = (Delete)statement; return setDelete(delete); } else { throw new ParseException("No supported sentence"); } } public Builder setPlainSelect(PlainSelect plainSelect) throws com.github.vincentrussell.query.mongodb.sql.converter.ParseException, ParseException { SqlUtils.isTrue(plainSelect != null, "could not parseNaturalLanguageDate SELECT statement from query"); SqlUtils.isTrue(plainSelect.getFromItem()!=null,"could not find table to query. Only one simple table name is supported."); whereClause = plainSelect.getWhere(); isDistinct = (plainSelect.getDistinct() != null); isCountAll = SqlUtils.isCountAll(plainSelect.getSelectItems()); SqlUtils.isTrue(plainSelect.getFromItem() != null, "could not find table to query. Only one simple table name is supported."); from = generateFromHolder(new FromHolder(this.defaultFieldType,this.fieldNameToFieldTypeMapping),plainSelect.getFromItem(),plainSelect.getJoins()); limit = SqlUtils.getLimit(plainSelect.getLimit()); offset = SqlUtils.getOffset(plainSelect.getOffset()); orderByElements1 = plainSelect.getOrderByElements(); selectItems = plainSelect.getSelectItems(); joins = plainSelect.getJoins(); groupBys = SqlUtils.getGroupByColumnReferences(plainSelect); havingClause = plainSelect.getHaving(); aliasHolder = generateHashAliasFromSelectItems(selectItems); isTotalGroup = SqlUtils.isTotalGroup(selectItems); SqlUtils.isTrue(plainSelect.getFromItem() != null, "could not find table to query. Only one simple table name is supported."); return this; } public Builder setDelete(Delete delete) throws com.github.vincentrussell.query.mongodb.sql.converter.ParseException, ParseException { SqlUtils.isTrue(delete.getTables().size() == 0, "there should only be on table specified for deletes"); from = generateFromHolder(new FromHolder(this.defaultFieldType,this.fieldNameToFieldTypeMapping),delete.getTable(),null); whereClause = delete.getWhere(); return this; } private AliasHolder generateHashAliasFromSelectItems(List<SelectItem> selectItems) { HashMap<String,String> aliasFromFieldHash = new HashMap<String,String>(); HashMap<String,String> fieldFromAliasHash = new HashMap<String,String>(); for(SelectItem sitem: selectItems) { if(!(sitem instanceof AllColumns)) { if(sitem instanceof SelectExpressionItem) { SelectExpressionItem seitem = (SelectExpressionItem) sitem; if(seitem.getAlias() != null) { Expression selectExp = seitem.getExpression(); selectExp.accept(new ExpVisitorEraseAliasTableBaseBuilder(this.from.getBaseAliasTable())); String expStr = selectExp.toString(); String aliasStr = seitem.getAlias().getName(); aliasFromFieldHash.put( expStr, aliasStr); fieldFromAliasHash.put( aliasStr, expStr); } } } } return new AliasHolder(aliasFromFieldHash, fieldFromAliasHash); } public SQLCommandInfoHolder build() { return new SQLCommandInfoHolder(sqlCommandType, whereClause, isDistinct, isCountAll, isTotalGroup, from, limit, offset, selectItems, joins, groupBys, orderByElements1, aliasHolder, havingClause); } public static Builder create(FieldType defaultFieldType, Map<String, FieldType> fieldNameToFieldTypeMapping) { return new Builder(defaultFieldType, fieldNameToFieldTypeMapping); } } }