Skip to content

feature suggest: simplify the example class generated #1022

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
WestFarmer opened this issue May 24, 2023 · 1 comment
Closed

feature suggest: simplify the example class generated #1022

WestFarmer opened this issue May 24, 2023 · 1 comment
Labels

Comments

@WestFarmer
Copy link

WestFarmer commented May 24, 2023

currently, the generated example can be relatively large and lacking support of free forms of SQL conditions:

for example:

`(A or B) and C`

is not directly supported, we need to convert it as :

`(A and C) or (B and C)`

I suggest a recursive way to represent SQL conditions:

public class Filter {
	
	private String field;
        // 'and' | 'or'
	private FilterLogic logic;

	private FilterOperator operator;

	private Object value;

	private List<Filter> filters;
        
       // getters and setters
}

then add it to example class, also add a method to generate where clause, I believe it's not possible to do so with xml, because xml elements not support recursive structure.

 // --- drat implementations not fully tested ---
public String getWhereClause() {
	return convertFilterToSQL(filter, 0, new int[filter.getDepth()]);
}

private String convertFilterToSQL(Filter filter, int depth, int[] idxs) {
		String buffer = "";
		String field = filter.getField();
		if (field != null) {
			String left = getColumn(field);
			String chain = getChainedValueExpression(field, depth, idxs);
			// boolean types in database can be used as condition directly
			if (filter.getOperator() == null) {
				buffer += left;
			} else if (filter.getOperator() == FilterOperator.IN || filter.getOperator() == FilterOperator.NOT_IN) {
				Object o = filter.getValue();
				List<Object> os = (List<Object>) o;
				String[] ss = new String[os.size()];
				for (int i = 0; i < os.size(); i++) {
					ss[i] = "#{filter" + chain + ".value[" + i + "]}";
				}
				buffer += left + " " + filter.getOperator().getSQLCondition() + " " + StringUtil.join(ss, "(", ", ", ")");
			} else if (filter.getOperator() == FilterOperator.BETWEEN || filter.getOperator() == FilterOperator.NOT_BETWEEN) {
				buffer += left + " " + filter.getOperator().getSQLCondition() + " #{filter" + chain + ".value[0]} and #{filter" + chain + ".value[1]}";
			} else if (filter.getOperator() == FilterOperator.IS_NULL || filter.getOperator() == FilterOperator.IS_NOT_NULL) {
				buffer += left + " " + filter.getOperator().getSQLCondition();
			} else {
				buffer += left + " " + filter.getOperator().getSQLCondition() + " #{filter" + chain + ".value}";
			}

		} else if (filter.getLogic() == FilterLogic.OR) {
			String[] ss = new String[filter.getFilters().size()];
			for (int i = 0; i < filter.getFilters().size(); i++) {
				idxs[depth] = i;
				ss[i] = convertFilterToSQL(filter.getFilters().get(i), depth + 1, idxs);

			}
			buffer += StringUtil.join(ss, "(", " or ", ")");
		} else if (filter.getLogic() == FilterLogic.AND) {
			String[] ss = new String[filter.getFilters().size()];
			for (int i = 0; i < filter.getFilters().size(); i++) {
				idxs[depth] = i;
				ss[i] = convertFilterToSQL(filter.getFilters().get(i), depth + 1, idxs);
			}
			buffer += StringUtil.join(ss, "(", " and ", ")");
		}
		return buffer;
	}

private String getChainedValueExpression(String field, int depth, int[] idxs) {
		System.out.println(depth + ":" + StringUtil.join(idxs, "[", ", ", "]"));
		if (depth == 0) {
			return ".";
		} else {
			String s = "";
			for (int i = 0; i < depth; i++) {
				s += ".filters[" + idxs[i] + "]";
			}
			return s;
		}
	}

then use it in xmls:

<if test="_parameter.filter != null">
where ${_parameter.getWhereClause()}
</if>

and we also need a fluent api to build filters.

@jeffgbutler
Copy link
Member

Please take a look at the newer generator runtimes that generate code for https://github.com/mybatis/mybatis-dynamic-sql. The XML based generators are deprecated because - as you say - XML based code is very brittle and low function. I built the new runtimes to address issues like you are raising here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants