Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.github.ashwithpoojary98.Query Maven / Gradle / Ivy
package io.github.ashwithpoojary98;
import io.github.ashwithpoojary98.annotations.ColumnAttribute;
import io.github.ashwithpoojary98.annotations.IgnoreAttribute;
import io.github.ashwithpoojary98.annotations.KeyAttribute;
import io.github.ashwithpoojary98.clausses.AggregateClause;
import io.github.ashwithpoojary98.clausses.columns.AggregatedColumn;
import io.github.ashwithpoojary98.clausses.columns.Column;
import io.github.ashwithpoojary98.clausses.columns.QueryColumn;
import io.github.ashwithpoojary98.clausses.columns.RawColumn;
import io.github.ashwithpoojary98.clausses.combines.Combine;
import io.github.ashwithpoojary98.clausses.combines.RawCombine;
import io.github.ashwithpoojary98.clausses.conditions.BasicCondition;
import io.github.ashwithpoojary98.clausses.conditions.BasicDateCondition;
import io.github.ashwithpoojary98.clausses.conditions.BasicStringCondition;
import io.github.ashwithpoojary98.clausses.conditions.BetweenCondition;
import io.github.ashwithpoojary98.clausses.conditions.BooleanCondition;
import io.github.ashwithpoojary98.clausses.conditions.ExistsCondition;
import io.github.ashwithpoojary98.clausses.conditions.InCondition;
import io.github.ashwithpoojary98.clausses.conditions.InQueryCondition;
import io.github.ashwithpoojary98.clausses.conditions.NestedCondition;
import io.github.ashwithpoojary98.clausses.conditions.NullCondition;
import io.github.ashwithpoojary98.clausses.conditions.QueryCondition;
import io.github.ashwithpoojary98.clausses.conditions.RawCondition;
import io.github.ashwithpoojary98.clausses.conditions.TwoColumnsCondition;
import io.github.ashwithpoojary98.clausses.fromclausses.AdHocTableFromClause;
import io.github.ashwithpoojary98.clausses.fromclausses.FromClause;
import io.github.ashwithpoojary98.clausses.fromclausses.QueryFromClause;
import io.github.ashwithpoojary98.clausses.fromclausses.RawFromClause;
import io.github.ashwithpoojary98.clausses.incrementclauses.IncrementClause;
import io.github.ashwithpoojary98.clausses.insertclauses.InsertClause;
import io.github.ashwithpoojary98.clausses.insertclauses.InsertQueryClause;
import io.github.ashwithpoojary98.clausses.joins.BaseJoin;
import io.github.ashwithpoojary98.clausses.limits.LimitClause;
import io.github.ashwithpoojary98.clausses.offsetclauses.OffsetClause;
import io.github.ashwithpoojary98.clausses.orderbyclauses.OrderBy;
import io.github.ashwithpoojary98.clausses.orderbyclauses.OrderByRandom;
import io.github.ashwithpoojary98.clausses.orderbyclauses.RawOrderBy;
import io.github.ashwithpoojary98.compilers.EngineCodes;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
public class Query extends BaseQuery {
private String comment;
private boolean isDistinct = false;
private String queryAlias;
private String method = "select";
private List includes = new ArrayList<>();
private Map variables = new HashMap<>();
private static final Map, Field[]> cacheDictionaryProperties = new ConcurrentHashMap<>();
public Query() {
super();
}
public Query(String table) {
super();
from(table);
}
public Query(String table, String comment) {
super();
from(table);
comment(comment);
}
public void setIsDistinct(boolean isDistinct) {
this.isDistinct = isDistinct;
}
public boolean getIsDistinct() {
return isDistinct;
}
public void setMethod(String method) {
this.method = method;
}
public String getMethod() {
return this.method;
}
public String getComment() {
return comment != null ? comment : "";
}
public void setQueryAlias(String queryAlias) {
this.queryAlias = queryAlias;
}
public String getQueryAlias() {
return this.queryAlias;
}
public boolean hasOffset(String engineCode) {
return getOffset(engineCode) > 0;
}
public boolean hasLimit(String engineCode) {
return getLimit(engineCode) > 0;
}
public int getOffset(String engineCode) {
engineCode = engineCode != null ? engineCode : engineScope;
OffsetClause offset = getOneComponent("offset", engineCode);
return offset != null ? offset.getOffset() : 0;
}
public int getLimit(String engineCode) {
engineCode = engineCode != null ? engineCode : engineScope;
LimitClause limit = getOneComponent("limit", engineCode);
return limit != null ? limit.getLimit() : 0;
}
@Override
public Query copy() {
Query clone = super.copy();
clone.parent = this.parent;
clone.queryAlias = this.queryAlias;
clone.isDistinct = this.isDistinct;
clone.method = this.method;
clone.includes = new ArrayList<>(this.includes);
clone.variables = new HashMap<>(this.variables);
return clone;
}
public Query as(String alias) {
this.queryAlias = alias;
return this;
}
public Query comment(String comment) {
this.comment = comment;
return this;
}
public Query forEngine(String engine, Function fn) {
String previousEngineScope = engineScope;
engineScope = engine;
Query result = fn.apply(this);
engineScope = previousEngineScope;
return result;
}
public Query forEngine(EngineCodes engine, Function fn) {
return forEngine(engine.getCode(), fn);
}
public Query with(Query query) {
if (query.queryAlias == null || query.queryAlias.trim().isEmpty()) {
throw new IllegalStateException("No Alias found for the CTE query");
}
Query clonedQuery = query.copy();
String alias = clonedQuery.queryAlias.trim();
clonedQuery.queryAlias = null;
return addComponent("cte", new QueryFromClause(clonedQuery, alias));
}
public Query with(Function fn) {
return with(fn.apply(new Query()));
}
public Query with(String alias, Query query) {
return with(query.as(alias));
}
public Query with(String alias, Function fn) {
return with(alias, fn.apply(new Query()));
}
public Query with(String alias, Iterable columns, Iterable> valuesCollection) {
List columnsList = columns != null ? StreamSupport.stream(columns.spliterator(), false).collect(Collectors.toList()) : null;
List> valuesCollectionList = valuesCollection != null ? StreamSupport.stream(valuesCollection.spliterator(), false).collect(Collectors.toList()) : null;
if ((columnsList == null || columnsList.isEmpty()) || (valuesCollectionList == null || valuesCollectionList.isEmpty())) {
throw new IllegalArgumentException("Columns and valuesCollection cannot be null or empty");
}
AdHocTableFromClause clause = new AdHocTableFromClause(alias, columnsList, new ArrayList<>());
for (Iterable values : valuesCollectionList) {
List valuesList = StreamSupport.stream(values.spliterator(), false).collect(Collectors.toList());
if (columnsList.size() != valuesList.size()) {
throw new IllegalArgumentException("Columns count should be equal to each Values count");
}
clause.getValues().addAll(valuesList);
}
return addComponent("cte", clause);
}
public Query withRaw(String alias, String sql, Object... bindings) {
return addComponent("cte", new RawFromClause(alias, sql, bindings));
}
public Query limit(int value) {
LimitClause newClause = new LimitClause(value);
return addOrReplaceComponent("limit", newClause);
}
public Query offset(int value) {
OffsetClause newClause = new OffsetClause(value);
return addOrReplaceComponent("offset", newClause);
}
public Query take(int limit) {
return limit(limit);
}
public Query skip(int offset) {
return offset(offset);
}
public Query forPage(int page, int perPage) {
return skip((page - 1) * perPage).take(perPage);
}
public Query distinct() {
isDistinct = true;
return this;
}
public Query when(boolean condition, Function whenTrue, Function whenFalse) {
if (condition && whenTrue != null) {
return whenTrue.apply(this);
}
if (!condition && whenFalse != null) {
return whenFalse.apply(this);
}
return this;
}
public Query whenNot(boolean condition, Function callback) {
if (!condition) {
return callback.apply(this);
}
return this;
}
public Query orderBy(String... columns) {
for (String column : columns) {
addComponent("order", new OrderBy(column, true));
}
return this;
}
public Query orderByDesc(String... columns) {
for (String column : columns) {
addComponent("order", new OrderBy(column, false));
}
return this;
}
public Query orderByRaw(String expression, Object... bindings) {
return addComponent("order", new RawOrderBy(expression, bindings));
}
public Query orderByRandom(String seed) {
return addComponent("order", new OrderByRandom());
}
public Query groupBy(String... columns) {
for (String column : columns) {
addComponent("group", new Column(column));
}
return this;
}
public Query groupByRaw(String expression, Object... bindings) {
addComponent("group", new RawColumn(expression, bindings));
return this;
}
@Override
public Query newQuery() {
return new Query();
}
public Query include(String relationName, Query query, String foreignKey, String localKey, boolean isMany) {
includes.add(new Include(relationName, query, foreignKey, localKey, isMany));
return this;
}
public Query includeMany(String relationName, Query query, String foreignKey, String localKey) {
return include(relationName, query, foreignKey, localKey, true);
}
public Query define(String variable, Object value) {
variables.put(variable, value);
return this;
}
public Object findVariable(String variable) {
if (variables.containsKey(variable)) {
return variables.get(variable);
}
if (parent != null) {
return ((Query) parent).findVariable(variable);
}
throw new IllegalArgumentException("Variable '" + variable + "' not found");
}
public Query having(String column, String op, Object value) {
if (value == null) {
return not(!op.equals("=")).havingNull(column);
}
BasicCondition condition = new BasicCondition(column, op, value, getOr(), getNot());
return addComponent("having", condition);
}
public Query havingNot(String column, String op, Object value) {
return not().having(column, op, value);
}
public Query orHaving(String column, String op, Object value) {
return or().having(column, op, value);
}
public Query orHavingNot(String column, String op, Object value) {
return or().not().having(column, op, value);
}
public Query having(String column, Object value) {
return having(column, "=", value);
}
public Query havingNot(String column, Object value) {
return havingNot(column, "=", value);
}
public Query orHaving(String column, Object value) {
return orHaving(column, "=", value);
}
public Query orHavingNot(String column, Object value) {
return orHavingNot(column, "=", value);
}
public Query having(Object constraints) {
Map dictionary = new HashMap<>();
// Use reflection to get properties from the constraints object
for (Field field : constraints.getClass().getDeclaredFields()) {
field.setAccessible(true); // Make private fields accessible
try {
dictionary.put(field.getName(), field.get(constraints));
} catch (IllegalAccessException e) {
// Handle the exception appropriately (log, rethrow, etc.)
}
}
return having(dictionary);
}
public Query having(Map values) {
Query query = this;
boolean orFlag = getOr();
boolean notFlag = getNot();
for (Map.Entry tuple : values.entrySet()) {
if (orFlag) {
query = query.or();
} else {
query.and();
}
query = this.not(notFlag).having(tuple.getKey(), tuple.getValue());
}
return query;
}
public Query havingRaw(String sql, Object... bindings) {
RawCondition condition = new RawCondition(sql, bindings, getOr(), getNot());
return addComponent("having", condition);
}
public Query orHavingRaw(String sql, Object... bindings) {
return or().havingRaw(sql, bindings);
}
public Query having(Function callback) {
Query query = callback.apply(newChild());
NestedCondition condition = new NestedCondition<>(query, getOr(), getNot());
return addComponent("having", condition);
}
public Query havingNot(Function callback) {
return not().having(callback);
}
public Query orHaving(Function callback) {
return or().having(callback);
}
public Query orHavingNot(Function callback) {
return not().or().having(callback);
}
public Query havingColumns(String first, String op, String second) {
TwoColumnsCondition condition = new TwoColumnsCondition(
first,
second,
op,
getOr(),
getNot());
return addComponent("having", condition);
}
public Query orHavingColumns(String first, String op, String second) {
return or().havingColumns(first, op, second);
}
public Query havingNull(String column) {
NullCondition condition = new NullCondition(column, getOr(), getNot());
return addComponent("having", condition);
}
public Query havingNotNull(String column) {
return not().havingNull(column);
}
public Query orHavingNull(String column) {
return or().havingNull(column);
}
public Query orHavingNotNull(String column) {
return or().not().havingNull(column);
}
public Query havingTrue(String column) {
return addComponent("having", new BooleanCondition(column, true));
}
public Query orHavingTrue(String column) {
return or().havingTrue(column);
}
public Query havingFalse(String column) {
return addComponent("having", new BooleanCondition(column, false));
}
public Query orHavingFalse(String column) {
return or().havingFalse(column);
}
public Query havingLike(String column, Object value, boolean caseSensitive, String escapeCharacter) {
BasicStringCondition condition = new BasicStringCondition(
"like",
column,
value,
caseSensitive,
escapeCharacter,
getOr(),
getNot());
return addComponent("having", condition);
}
// Overloaded method for default values
public Query havingLike(String column, Object value) {
return havingLike(column, value, false, null);
}
public Query havingNotLike(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return not().havingLike(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingLike(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().havingLike(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingNotLike(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().not().havingLike(column, value, caseSensitive, escapeCharacter);
}
// Overloaded methods for default values
public Query havingNotLike(String column, Object value) {
return havingNotLike(column, value, false, null);
}
public Query orHavingLike(String column, Object value) {
return orHavingLike(column, value, false, null);
}
public Query orHavingNotLike(String column, Object value) {
return orHavingNotLike(column, value, false, null);
}
public Query havingStarts(String column, Object value, boolean caseSensitive, String escapeCharacter) {
BasicStringCondition condition = new BasicStringCondition(
"starts",
column,
value,
caseSensitive,
escapeCharacter,
getOr(),
getNot());
return addComponent("having", condition);
}
// Overloaded method for default values
public Query havingStarts(String column, Object value) {
return havingStarts(column, value, false, null);
}
public Query havingNotStarts(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return not().havingStarts(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingStarts(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().havingStarts(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingNotStarts(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().not().havingStarts(column, value, caseSensitive, escapeCharacter);
}
// Overloaded methods for default values
public Query havingNotStarts(String column, Object value) {
return havingNotStarts(column, value, false, null);
}
public Query orHavingStarts(String column, Object value) {
return orHavingStarts(column, value, false, null);
}
public Query orHavingNotStarts(String column, Object value) {
return orHavingNotStarts(column, value, false, null);
}
public Query havingEnds(String column, Object value, boolean caseSensitive, String escapeCharacter) {
BasicStringCondition condition = new BasicStringCondition(
"ends",
column,
value,
caseSensitive,
escapeCharacter,
getOr(),
getNot());
return addComponent("having", condition);
}
// Overloaded method for default values
public Query havingEnds(String column, Object value) {
return havingEnds(column, value, false, null);
}
public Query havingNotEnds(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return not().havingEnds(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingEnds(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().havingEnds(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingNotEnds(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().not().havingEnds(column, value, caseSensitive, escapeCharacter);
}
// Overloaded methods for default values
public Query havingNotEnds(String column, Object value) {
return havingNotEnds(column, value, false, null);
}
public Query orHavingEnds(String column, Object value) {
return orHavingEnds(column, value, false, null);
}
public Query orHavingNotEnds(String column, Object value) {
return orHavingNotEnds(column, value, false, null);
}
public Query havingContains(String column, Object value, boolean caseSensitive, String escapeCharacter) {
BasicStringCondition condition = new BasicStringCondition(
"contains",
column,
value,
caseSensitive,
escapeCharacter,
getOr(),
getNot());
return addComponent("having", condition);
}
// Overloaded method for default values
public Query havingContains(String column, Object value) {
return havingContains(column, value, false, null);
}
public Query havingNotContains(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return not().havingContains(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingContains(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().havingContains(column, value, caseSensitive, escapeCharacter);
}
public Query orHavingNotContains(String column, Object value, boolean caseSensitive, String escapeCharacter) {
return or().not().havingContains(column, value, caseSensitive, escapeCharacter);
}
// Overloaded methods for default values
public Query havingNotContains(String column, Object value) {
return havingNotContains(column, value, false, null);
}
public Query orHavingContains(String column, Object value) {
return orHavingContains(column, value, false, null);
}
public Query orHavingNotContains(String column, Object value) {
return orHavingNotContains(column, value, false, null);
}
public Query havingBetween(String column, T lower, T higher) {
BetweenCondition condition = new BetweenCondition<>(
column,
getOr(),
getNot(),
lower,
higher);
return addComponent("having", condition);
}
public Query orHavingBetween(String column, T lower, T higher) {
return or().havingBetween(column, lower, higher);
}
public Query havingNotBetween(String column, T lower, T higher) {
return not().havingBetween(column, lower, higher);
}
public Query orHavingNotBetween(String column, T lower, T higher) {
return or().not().havingBetween(column, lower, higher);
}
public Query havingIn(String column, List values) {
InCondition condition = new InCondition<>(
column,
getOr(),
getNot(),
values);
return addComponent("having", condition);
}
public Query orHavingIn(String column, List values) {
return or().havingIn(column, values);
}
public Query havingNotIn(String column, List values) {
return not().havingIn(column, values);
}
public Query orHavingNotIn(String column, List values) {
return or().not().havingIn(column, values);
}
public Query havingIn(String column, Query query) {
InQueryCondition condition = new InQueryCondition(
column,
getOr(),
getNot(),
query);
return addComponent("having", condition);
}
public Query havingIn(String column, Function callback) {
Query query = callback.apply(new Query());
return havingIn(column, query);
}
public Query orHavingIn(String column, Query query) {
return or().havingIn(column, query);
}
public Query orHavingIn(String column, Function callback) {
return or().havingIn(column, callback);
}
public Query havingNotIn(String column, Query query) {
return not().havingIn(column, query);
}
public Query havingNotIn(String column, Function callback) {
return not().havingIn(column, callback);
}
public Query orHavingNotIn(String column, Query query) {
return or().not().havingIn(column, query);
}
public Query orHavingNotIn(String column, Function callback) {
return or().not().havingIn(column, callback);
}
public Query having(String column, String op, Function callback) {
Query query = callback.apply(newChild());
return having(column, op, query);
}
public Query having(String column, String op, Query query) {
QueryCondition condition = new QueryCondition<>(
column,
op,
query,
getOr(),
getNot());
return addComponent("having", condition);
}
public Query orHaving(String column, String op, Query query) {
return or().having(column, op, query);
}
public Query orHaving(String column, String op, Function callback) {
return or().having(column, op, callback);
}
public Query havingExists(Query query) {
if (!query.hasComponent("from")) {
throw new IllegalArgumentException(String.format("%s cannot be empty if used inside a %s condition",
FromClause.class.getSimpleName(),
"HavingExists"));
}
// Simplify the query as much as possible
query = query.copy().clearComponent("select")
.selectRaw("1")
.limit(1);
ExistsCondition condition = new ExistsCondition(
query,
getOr(),
getNot());
return addComponent("having", condition);
}
public Query havingExists(Function callback) {
Query childQuery = new Query().setParent(this);
return havingExists(callback.apply(childQuery));
}
public Query havingNotExists(Query query) {
return not().havingExists(query);
}
public Query havingNotExists(Function callback) {
return not().havingExists(callback);
}
public Query orHavingExists(Query query) {
return or().havingExists(query);
}
public Query orHavingExists(Function callback) {
return or().havingExists(callback);
}
public Query orHavingNotExists(Query query) {
return or().not().havingExists(query);
}
public Query orHavingNotExists(Function callback) {
return or().not().havingExists(callback);
}
public Query havingDatePart(String part, String column, String op, Object value) {
BasicDateCondition condition = new BasicDateCondition(
op,
column,
value,
part,
getOr(),
getNot());
return addComponent("having", condition);
}
public Query havingNotDatePart(String part, String column, String op, Object value) {
return not().havingDatePart(part, column, op, value);
}
public Query orHavingDatePart(String part, String column, String op, Object value) {
return or().havingDatePart(part, column, op, value);
}
public Query orHavingNotDatePart(String part, String column, String op, Object value) {
return or().not().havingDatePart(part, column, op, value);
}
public Query havingDate(String column, String op, Object value) {
return havingDatePart("date", column, op, value);
}
public Query havingNotDate(String column, String op, Object value) {
return not().havingDate(column, op, value);
}
public Query orHavingDate(String column, String op, Object value) {
return or().havingDate(column, op, value);
}
public Query orHavingNotDate(String column, String op, Object value) {
return or().not().havingDate(column, op, value);
}
public Query havingTime(String column, String op, Object value) {
return havingDatePart("time", column, op, value);
}
public Query havingNotTime(String column, String op, Object value) {
return not().havingTime(column, op, value);
}
public Query orHavingTime(String column, String op, Object value) {
return or().havingTime(column, op, value);
}
public Query orHavingNotTime(String column, String op, Object value) {
return or().not().havingTime(column, op, value);
}
public Query havingDatePart(String part, String column, Object value) {
return havingDatePart(part, column, "=", value);
}
public Query havingNotDatePart(String part, String column, Object value) {
return havingNotDatePart(part, column, "=", value);
}
public Query orHavingDatePart(String part, String column, Object value) {
return orHavingDatePart(part, column, "=", value);
}
public Query orHavingNotDatePart(String part, String column, Object value) {
return orHavingNotDatePart(part, column, "=", value);
}
public Query havingDate(String column, Object value) {
return havingDate(column, "=", value);
}
public Query havingNotDate(String column, Object value) {
return havingNotDate(column, "=", value);
}
public Query orHavingDate(String column, Object value) {
return orHavingDate(column, "=", value);
}
public Query orHavingNotDate(String column, Object value) {
return orHavingNotDate(column, "=", value);
}
public Query havingTime(String column, Object value) {
return havingTime(column, "=", value);
}
public Query havingNotTime(String column, Object value) {
return havingNotTime(column, "=", value);
}
public Query orHavingTime(String column, Object value) {
return orHavingTime(column, "=", value);
}
public Query orHavingNotTime(String column, Object value) {
return orHavingNotTime(column, "=", value);
}
public Query asAggregate(String type, String[] columns) {
this.method = "aggregate";
this.clearComponent("aggregate")
.addComponent("aggregate", new AggregateClause(type, columns != null ? Arrays.asList(columns) : new ArrayList<>()));
return this;
}
public Query asCount(String[] columns) {
List cols = columns != null ? Arrays.asList(columns) : new ArrayList<>();
if (cols.isEmpty()) {
cols.add("*");
}
return asAggregate("count", cols.toArray(new String[0]));
}
public Query asCount() {
return asCount(null);
}
public Query asAvg(String column) {
return asAggregate("avg", new String[]{column});
}
public Query asAverage(String column) {
return asAvg(column);
}
public Query asSum(String column) {
return asAggregate("sum", new String[]{column});
}
public Query asMax(String column) {
return asAggregate("max", new String[]{column});
}
public Query asMin(String column) {
return asAggregate("min", new String[]{column});
}
public Query combine(String operation, boolean all, Query query) {
if (!this.method.equals("select") || !query.method.equals("select")) {
throw new IllegalStateException("Only select queries can be combined.");
}
return addComponent("combine", new Combine(query, operation, all));
}
public Query combineRaw(String sql, Object... bindings) {
if (!this.method.equals("select")) {
throw new IllegalStateException("Only select queries can be combined.");
}
return addComponent("combine", new RawCombine(sql, bindings));
}
public Query union(Query query, boolean all) {
return combine("union", all, query);
}
public Query unionAll(Query query) {
return union(query, true);
}
public Query union(Function callback, boolean all) {
Query query = callback.apply(new Query());
return union(query, all);
}
public Query unionAll(Function callback) {
return union(callback, true);
}
public Query unionRaw(String sql, Object... bindings) {
return combineRaw(sql, bindings);
}
public Query except(Query query, boolean all) {
return combine("except", all, query);
}
public Query exceptAll(Query query) {
return except(query, true);
}
public Query except(Function callback, boolean all) {
Query query = callback.apply(new Query());
return except(query, all);
}
public Query exceptAll(Function callback) {
return except(callback, true);
}
public Query exceptRaw(String sql, Object... bindings) {
return combineRaw(sql, bindings);
}
public Query intersect(Query query, boolean all) {
return combine("intersect", all, query);
}
public Query intersectAll(Query query) {
return intersect(query, true);
}
public Query intersect(Function callback, boolean all) {
Query query = callback.apply(new Query());
return intersect(query, all);
}
public Query intersectAll(Function callback) {
return intersect(callback, true);
}
public Query intersectRaw(String sql, Object... bindings) {
return combineRaw(sql, bindings);
}
public Query asDelete() {
this.method = "delete";
return this;
}
public Query asInsert(Object data, boolean returnId) {
Map propertiesKeyValues = buildKeyValuePairsFromObject(data);
return asInsert(propertiesKeyValues, returnId);
}
public Query asInsert(Map values, boolean returnId) {
if (values == null || values.isEmpty()) {
throw new IllegalArgumentException("values argument cannot be null or empty");
}
method = "insert";
clearComponent("insert").addComponent("insert", new InsertClause(
new ArrayList<>(values.keySet()),
new ArrayList<>(values.values()),
returnId
));
return this;
}
public Query asInsert(List columns, List> rowsValues) {
if (columns == null || columns.isEmpty() || rowsValues == null || rowsValues.isEmpty()) {
throw new IllegalArgumentException("columns and rowsValues cannot be null or empty");
}
method = "insert";
clearComponent("insert");
for (List values : rowsValues) {
if (columns.size() != values.size()) {
throw new IllegalArgumentException("columns count should be equal to each rowsValues entry count");
}
addComponent("insert", new InsertClause(columns, values));
}
return this;
}
public Query asInsert(List columns, Query query) {
method = "insert";
clearComponent("insert").addComponent("insert", new InsertQueryClause(columns, query.copy()));
return this;
}
private Query join(Function callback) {
Join join = callback.apply(new Join().asInner());
return addComponent("join", new BaseJoin(join));
}
public Query join(String table, String first, String second, String op, String type) {
return join(j -> j.joinWith(table).whereColumns(first, op, second).asType(type));
}
public Query join(String table, Function callback, String type) {
return join(j -> j.joinWith(table).where(callback).asType(type));
}
public Query join(Query query, Function onCallback, String type) {
return join(j -> j.joinWith(query).where(onCallback).asType(type));
}
public Query leftJoin(String table, String first, String second, String op) {
return join(table, first, second, op, "left join");
}
public Query leftJoin(String table, Function callback) {
return join(table, callback, "left join");
}
public Query leftJoin(Query query, Function onCallback) {
return join(query, onCallback, "left join");
}
public Query rightJoin(String table, String first, String second, String op) {
return join(table, first, second, op, "right join");
}
public Query rightJoin(String table, Function callback) {
return join(table, callback, "right join");
}
public Query rightJoin(Query query, Function onCallback) {
return join(query, onCallback, "right join");
}
public Query crossJoin(String table) {
return join(j -> j.joinWith(table).asCross());
}
public Query select(String... columns) {
return select(Arrays.asList(columns));
}
public Query select(Iterable columns) {
method = "select";
List expandedColumns = new ArrayList<>();
for (String column : columns) {
expandedColumns.addAll(Helper.expandExpression(column));
}
for (String column : expandedColumns) {
addComponent("select", new Column(column));
}
return this;
}
public Query selectRaw(String sql, Object... bindings) {
method = "select";
addComponent("select", new RawColumn(sql, bindings));
return this;
}
public Query select(Query query, String alias) {
method = "select";
Query clonedQuery = query.copy();
addComponent("select", new QueryColumn(clonedQuery.as(alias)));
return this;
}
public Query select(Function callback, String alias) {
return select(callback.apply(new Query().newChild()), alias);
}
public Query selectAggregate(String aggregate, String column, Query filter) {
method = "select";
addComponent("select", new AggregatedColumn(new Column(column), aggregate, filter));
return this;
}
public Query selectAggregate(String aggregate, String column, Function filter) {
if (filter == null) {
return selectAggregate(aggregate, column, (Query) null);
}
return selectAggregate(aggregate, column, filter.apply(new Query().newChild()));
}
public Query selectSum(String column, Function filter) {
return selectAggregate("sum", column, filter);
}
public Query selectCount(String column, Function filter) {
return selectAggregate("count", column, filter);
}
public Query selectAvg(String column, Function filter) {
return selectAggregate("avg", column, filter);
}
public Query selectMin(String column, Function filter) {
return selectAggregate("min", column, filter);
}
public Query selectMax(String column, Function filter) {
return selectAggregate("max", column, filter);
}
public Query asUpdate(Object data) {
Map dictionary = buildKeyValuePairsFromObject(data, true);
return asUpdate(dictionary);
}
public Query asUpdate(List columns, List values) {
if (columns == null || columns.isEmpty() || values == null || values.isEmpty()) {
throw new IllegalStateException(columns + " and " + values + " cannot be null or empty");
}
if (columns.size() != values.size()) {
throw new IllegalStateException(columns + " count should be equal to " + values + " count");
}
this.method = "update";
clearComponent("update").addComponent("update", new InsertClause(columns, values));
return this;
}
public Query asUpdate(Map values) {
if (values == null || values.isEmpty()) {
throw new IllegalStateException(values + " cannot be null or empty");
}
this.method = "update";
List columnName = new ArrayList<>();
List columnValue = new ArrayList<>();
values.forEach((key, value) -> {
columnName.add(key);
columnValue.add(value);
});
clearComponent("update").addComponent("update", new InsertClause(
columnName,
columnValue));
return this;
}
public Query asIncrement(String column, int value) {
this.method = "update";
addOrReplaceComponent("update", new IncrementClause(column, value));
return this;
}
public Query asIncrement(String column) {
return asIncrement(column, 1);
}
public Query asDecrement(String column, int value) {
return asIncrement(column, -value);
}
public Query asDecrement(String column) {
return asDecrement(column, 1);
}
// Main method to build key-value pairs
private Map buildKeyValuePairsFromObject(Object data, boolean considerKeys) {
if (data == null) {
throw new IllegalArgumentException("Data cannot be null");
}
Map dictionary = new HashMap<>();
Field[] fields = cacheDictionaryProperties.computeIfAbsent(data.getClass(), clazz -> clazz.getDeclaredFields());
for (Field field : fields) {
// Check if the field should be ignored
if (field.isAnnotationPresent(IgnoreAttribute.class)) {
continue;
}
// Access the field value
field.setAccessible(true); // Allow access to private fields
Object value;
try {
value = field.get(data);
} catch (IllegalAccessException e) {
throw new RuntimeException("Unable to access field: " + field.getName(), e);
}
// Get the column annotation
ColumnAttribute columnAttr = field.getAnnotation(ColumnAttribute.class);
String name = (columnAttr != null && !columnAttr.name().isEmpty()) ? columnAttr.name() : field.getName();
// Add to dictionary
dictionary.put(name, value);
// Handle keys if considerKeys is true
if (considerKeys && columnAttr != null && field.isAnnotationPresent(KeyAttribute.class)) {
where(name, value);
}
}
return dictionary;
}
private Map buildKeyValuePairsFromObject(Object data) {
return buildKeyValuePairsFromObject(data, false);
}
}