From f0efa50d4fb7bd151379a265a82fb3251bcb75f1 Mon Sep 17 00:00:00 2001 From: Vincenzo Guzzi Date: Fri, 21 Oct 2016 14:21:20 +0100 Subject: [PATCH] Adds leftJoin to QueryBuilder. --- .../greendao/query/QueryBuilder.java | 74 +++++++++++++++++-- 1 file changed, 67 insertions(+), 7 deletions(-) diff --git a/DaoCore/src/main/java/org/greenrobot/greendao/query/QueryBuilder.java b/DaoCore/src/main/java/org/greenrobot/greendao/query/QueryBuilder.java index a0667c02e..a9c154924 100644 --- a/DaoCore/src/main/java/org/greenrobot/greendao/query/QueryBuilder.java +++ b/DaoCore/src/main/java/org/greenrobot/greendao/query/QueryBuilder.java @@ -58,6 +58,7 @@ public class QueryBuilder { private final List values; private final List> joins; + private final List> leftJoins; private final AbstractDao dao; private final String tablePrefix; @@ -82,6 +83,7 @@ protected QueryBuilder(AbstractDao dao, String tablePrefix) { this.tablePrefix = tablePrefix; values = new ArrayList(); joins = new ArrayList>(); + leftJoins = new ArrayList>(); whereCollector = new WhereCollector(dao, tablePrefix); stringOrderCollation = " COLLATE NOCASE"; } @@ -205,6 +207,45 @@ public Join join(Join sourceJoin, Property sourceProperty, Class return addJoin(sourceJoin.tablePrefix, sourceProperty, destinationDao, destinationProperty); } + /** + * Expands the query to another entity type by using a LEFT JOIN. The primary key property of the primary entity for + * this QueryBuilder is used to match the given destinationProperty. + */ + public Join leftJoin(Class destinationEntityClass, Property destinationProperty) { + return leftJoin(dao.getPkProperty(), destinationEntityClass, destinationProperty); + } + + /** + * Expands the query to another entity type by using a LEFT JOIN. The given sourceProperty is used to match the primary + * key property of the given destinationEntity. + */ + public Join leftJoin(Property sourceProperty, Class destinationEntityClass) { + AbstractDao destinationDao = (AbstractDao) dao.getSession().getDao(destinationEntityClass); + Property destinationProperty = destinationDao.getPkProperty(); + return addLeftJoin(tablePrefix, sourceProperty, destinationDao, destinationProperty); + } + + /** + * Expands the query to another entity type by using a LEFT JOIN. The given sourceProperty is used to match the given + * destinationProperty of the given destinationEntity. + */ + public Join leftJoin(Property sourceProperty, Class destinationEntityClass, Property destinationProperty) { + AbstractDao destinationDao = (AbstractDao) dao.getSession().getDao(destinationEntityClass); + return addLeftJoin(tablePrefix, sourceProperty, destinationDao, destinationProperty); + } + + /** + * Expands the query to another entity type by using a LEFT JOIN. The given sourceJoin's property is used to match the + * given destinationProperty of the given destinationEntity. Note that destination entity of the given join is used + * as the source for the new join to add. In this way, it is possible to compose complex "join of joins" across + * several entities if required. + */ + public Join leftJoin(Join sourceJoin, Property sourceProperty, Class destinationEntityClass, + Property destinationProperty) { + AbstractDao destinationDao = (AbstractDao) dao.getSession().getDao(destinationEntityClass); + return addLeftJoin(sourceJoin.tablePrefix, sourceProperty, destinationDao, destinationProperty); + } + private Join addJoin(String sourceTablePrefix, Property sourceProperty, AbstractDao destinationDao, Property destinationProperty) { String joinTablePrefix = "J" + (joins.size() + 1); @@ -214,6 +255,15 @@ private Join addJoin(String sourceTablePrefix, Property sourceProperty return join; } + private Join addLeftJoin(String sourceTablePrefix, Property sourceProperty, AbstractDao destinationDao, + Property destinationProperty) { + String joinTablePrefix = "LJ" + (leftJoins.size() + 1); + Join join = new Join(sourceTablePrefix, sourceProperty, destinationDao, destinationProperty, + joinTablePrefix); + leftJoins.add(join); + return join; + } + /** Adds the given properties to the ORDER BY section using ascending order. */ public QueryBuilder orderAsc(Property... properties) { orderAscOrDesc(" ASC", properties); @@ -347,7 +397,7 @@ private int checkAddOffset(StringBuilder builder) { * QueryBuilder for each execution. */ public DeleteQuery buildDelete() { - if (!joins.isEmpty()) { + if (!joins.isEmpty() || !leftJoins.isEmpty()) { throw new DaoException("JOINs are not supported for DELETE queries"); } String tablename = dao.getTablename(); @@ -394,17 +444,27 @@ private void checkLog(String sql) { private void appendJoinsAndWheres(StringBuilder builder, String tablePrefixOrNull) { values.clear(); - for (Join join : joins) { - builder.append(" JOIN ").append(join.daoDestination.getTablename()).append(' '); - builder.append(join.tablePrefix).append(" ON "); - SqlUtils.appendProperty(builder, join.sourceTablePrefix, join.joinPropertySource).append('='); - SqlUtils.appendProperty(builder, join.tablePrefix, join.joinPropertyDestination); - } + appendJoins(builder, joins, " JOIN "); + appendJoins(builder, leftJoins, " LEFT JOIN "); boolean whereAppended = !whereCollector.isEmpty(); if (whereAppended) { builder.append(" WHERE "); whereCollector.appendWhereClause(builder, tablePrefixOrNull, values); } + appendJoinWheres(builder, joins, whereAppended); + appendJoinWheres(builder, leftJoins, whereAppended); + } + + private void appendJoins(StringBuilder builder, List> joins, String joinType) { + for (Join join : joins) { + builder.append(joinType).append(join.daoDestination.getTablename()).append(' '); + builder.append(join.tablePrefix).append(" ON "); + SqlUtils.appendProperty(builder, join.sourceTablePrefix, join.joinPropertySource).append('='); + SqlUtils.appendProperty(builder, join.tablePrefix, join.joinPropertyDestination); + } + } + + private void appendJoinWheres(StringBuilder builder, List> joins, boolean whereAppended) { for (Join join : joins) { if (!join.whereCollector.isEmpty()) { if (!whereAppended) {