killbill-memoizeit
Changes
subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java 6(+3 -3)
Details
diff --git a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
index b959cb7..6ca2fa3 100644
--- a/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
+++ b/account/src/main/java/org/killbill/billing/account/dao/DefaultAccountDao.java
@@ -40,6 +40,7 @@ import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Pagination;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
import org.killbill.billing.util.entity.dao.EntityDaoBase;
import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
@@ -139,8 +140,8 @@ public class DefaultAccountDao extends EntityDaoBase<AccountModelDao, Account, A
}
@Override
- public Iterator<AccountModelDao> build(final AccountSqlDao accountSqlDao, final Long limit, final InternalTenantContext context) {
- return accountSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ public Iterator<AccountModelDao> build(final AccountSqlDao accountSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return accountSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
}
},
offset,
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
index c452e53..4d64d57 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/dao/DefaultInvoiceDao.java
@@ -61,6 +61,7 @@ import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.config.definition.InvoiceConfig;
import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.billing.util.entity.Pagination;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
import org.killbill.billing.util.entity.dao.EntityDaoBase;
import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
@@ -371,11 +372,11 @@ public class DefaultInvoiceDao extends EntityDaoBase<InvoiceModelDao, Invoice, I
}
@Override
- public Iterator<InvoiceModelDao> build(final InvoiceSqlDao invoiceSqlDao, final Long limit, final InternalTenantContext context) {
+ public Iterator<InvoiceModelDao> build(final InvoiceSqlDao invoiceSqlDao, final Long offset, final Long limit, final DefaultPaginationSqlDaoHelper.Ordering ordering, final InternalTenantContext context) {
try {
return invoiceNumber != null ?
ImmutableList.<InvoiceModelDao>of(getByNumber(invoiceNumber, context)).iterator() :
- invoiceSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ invoiceSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
} catch (final InvoiceApiException ignored) {
return Iterators.<InvoiceModelDao>emptyIterator();
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
index 020ff49..4d00d40 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/DefaultPaymentDao.java
@@ -53,6 +53,7 @@ import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.billing.util.entity.Entity;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
import org.killbill.billing.util.entity.dao.EntityDaoBase;
import org.killbill.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
@@ -150,8 +151,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
return sqlDao.getCountByStateNameAcrossTenants(stateName, createdBefore);
}
@Override
- public Iterator<PaymentAttemptModelDao> build(final PaymentAttemptSqlDao sqlDao, final Long limit, final InternalTenantContext context) {
- return sqlDao.getByStateNameAcrossTenants(stateName, createdBefore, offset, limit);
+ public Iterator<PaymentAttemptModelDao> build(final PaymentAttemptSqlDao sqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return sqlDao.getByStateNameAcrossTenants(stateName, createdBefore, offset, limit, ordering.toString());
}
},
offset,
@@ -200,8 +201,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
}
@Override
- public Iterator<PaymentTransactionModelDao> build(final TransactionSqlDao sqlDao, final Long limit, final InternalTenantContext context) {
- return sqlDao.getByTransactionStatusPriorDateAcrossTenants(allTransactionStatus, createdBefore, createdAfter, offset, limit);
+ public Iterator<PaymentTransactionModelDao> build(final TransactionSqlDao sqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return sqlDao.getByTransactionStatusPriorDateAcrossTenants(allTransactionStatus, createdBefore, createdAfter, offset, limit, ordering.toString());
}
},
offset,
@@ -240,8 +241,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
}
@Override
- public Iterator<PaymentModelDao> build(final PaymentSqlDao paymentSqlDao, final Long limit, final InternalTenantContext context) {
- final Iterator<PaymentModelDao> result = paymentSqlDao.getByPluginName(pluginName, offset, limit, context);
+ public Iterator<PaymentModelDao> build(final PaymentSqlDao paymentSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ final Iterator<PaymentModelDao> result = paymentSqlDao.getByPluginName(pluginName, offset, limit, ordering.toString(), context);
return result;
}
},
@@ -265,8 +266,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
}
@Override
- public Iterator<PaymentModelDao> build(final PaymentSqlDao paymentSqlDao, final Long limit, final InternalTenantContext context) {
- return !paymentStates.isEmpty() ? paymentSqlDao.searchByState(paymentStates, offset, limit, context) : paymentSqlDao.search(searchKey, likeSearchKey, offset, limit, context);
+ public Iterator<PaymentModelDao> build(final PaymentSqlDao paymentSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return !paymentStates.isEmpty() ? paymentSqlDao.searchByState(paymentStates, offset, limit, ordering.toString(), context) : paymentSqlDao.search(searchKey, likeSearchKey, offset, limit, ordering.toString(), context);
}
},
offset,
@@ -492,8 +493,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
}
@Override
- public Iterator<PaymentMethodModelDao> build(final PaymentMethodSqlDao paymentMethodSqlDao, final Long limit, final InternalTenantContext context) {
- return paymentMethodSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ public Iterator<PaymentMethodModelDao> build(final PaymentMethodSqlDao paymentMethodSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return paymentMethodSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
}
},
offset,
@@ -511,8 +512,8 @@ public class DefaultPaymentDao extends EntityDaoBase<PaymentModelDao, Payment, P
}
@Override
- public Iterator<PaymentMethodModelDao> build(final PaymentMethodSqlDao paymentMethodSqlDao, final Long limit, final InternalTenantContext context) {
- return paymentMethodSqlDao.getByPluginName(pluginName, offset, limit, context);
+ public Iterator<PaymentMethodModelDao> build(final PaymentMethodSqlDao paymentMethodSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return paymentMethodSqlDao.getByPluginName(pluginName, offset, limit, ordering.toString(), context);
}
},
offset,
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.java
index 4b25a00..d9aef5d 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.java
@@ -31,6 +31,7 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
@EntitySqlDaoStringTemplate
public interface PaymentAttemptSqlDao extends EntitySqlDao<PaymentAttemptModelDao, Entity> {
@@ -66,6 +67,7 @@ public interface PaymentAttemptSqlDao extends EntitySqlDao<PaymentAttemptModelDa
Iterator<PaymentAttemptModelDao> getByStateNameAcrossTenants(@Bind("stateName") final String stateName,
@Bind("createdBeforeDate") final Date createdBeforeDate,
@Bind("offset") final Long offset,
- @Bind("rowCount") final Long rowCount);
+ @Bind("rowCount") final Long rowCount,
+ @Define("ordering") final String ordering);
}
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentMethodSqlDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentMethodSqlDao.java
index ec7cc3d..da14f3e 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentMethodSqlDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentMethodSqlDao.java
@@ -34,6 +34,7 @@ import org.killbill.billing.util.audit.ChangeType;
import org.killbill.billing.util.entity.dao.Audited;
import org.killbill.billing.util.entity.dao.EntitySqlDao;
import org.killbill.billing.util.entity.dao.EntitySqlDaoStringTemplate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
@EntitySqlDaoStringTemplate
public interface PaymentMethodSqlDao extends EntitySqlDao<PaymentMethodModelDao, PaymentMethod> {
@@ -69,6 +70,7 @@ public interface PaymentMethodSqlDao extends EntitySqlDao<PaymentMethodModelDao,
public Iterator<PaymentMethodModelDao> getByPluginName(@Bind("pluginName") final String pluginName,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
+ @Define("ordering") final String ordering,
@BindBean final InternalTenantContext context);
@SqlQuery
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentSqlDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentSqlDao.java
index 23dcd3f..2be09a6 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/PaymentSqlDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/PaymentSqlDao.java
@@ -33,6 +33,7 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
@EntitySqlDaoStringTemplate
public interface PaymentSqlDao extends EntitySqlDao<PaymentModelDao, Payment> {
@@ -71,6 +72,7 @@ public interface PaymentSqlDao extends EntitySqlDao<PaymentModelDao, Payment> {
public Iterator<PaymentModelDao> searchByState(@PaymentStateCollectionBinder final Collection<String> paymentStates,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
+ @Define("ordering") final String ordering,
@BindBean final InternalTenantContext context);
@SqlQuery
@@ -82,7 +84,8 @@ public interface PaymentSqlDao extends EntitySqlDao<PaymentModelDao, Payment> {
public Iterator<PaymentModelDao> getByPluginName(@Bind("pluginName") final String pluginName,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
- @BindBean final InternalTenantContext context);
+ @Define("ordering") final String ordering,
+ @BindBean final InternalTenantContext context);
@SqlQuery
public Long getCountByPluginName(@Bind("pluginName") final String pluginName,
diff --git a/payment/src/main/java/org/killbill/billing/payment/dao/TransactionSqlDao.java b/payment/src/main/java/org/killbill/billing/payment/dao/TransactionSqlDao.java
index d85ac3a..4f687aa 100644
--- a/payment/src/main/java/org/killbill/billing/payment/dao/TransactionSqlDao.java
+++ b/payment/src/main/java/org/killbill/billing/payment/dao/TransactionSqlDao.java
@@ -35,6 +35,7 @@ import org.skife.jdbi.v2.sqlobject.Bind;
import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Define;
@EntitySqlDaoStringTemplate
public interface TransactionSqlDao extends EntitySqlDao<PaymentTransactionModelDao, PaymentTransaction> {
@@ -61,10 +62,11 @@ public interface TransactionSqlDao extends EntitySqlDao<PaymentTransactionModelD
@SqlQuery
Iterator<PaymentTransactionModelDao> getByTransactionStatusPriorDateAcrossTenants(@TransactionStatusCollectionBinder final Collection<String> statuses,
- @Bind("createdBeforeDate") final Date createdBeforeDate,
- @Bind("createdAfterDate") final Date createdAfterDate,
- @Bind("offset") final Long offset,
- @Bind("rowCount") final Long rowCount);
+ @Bind("createdBeforeDate") final Date createdBeforeDate,
+ @Bind("createdAfterDate") final Date createdAfterDate,
+ @Bind("offset") final Long offset,
+ @Bind("rowCount") final Long rowCount,
+ @Define("ordering") final String ordering);
@SqlQuery
public List<PaymentTransactionModelDao> getByPaymentId(@Bind("paymentId") final UUID paymentId,
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
index d8f6437..d8699fe 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentAttemptSqlDao.sql.stg
@@ -65,14 +65,14 @@ where payment_external_key = :paymentExternalKey
>>
/* Does not include tenant info, global */
-getByStateNameAcrossTenants() ::= <<
+getByStateNameAcrossTenants(ordering) ::= <<
select
<allTableFields("")>
from <tableName()>
where state_name = :stateName
and created_date \< :createdBeforeDate
<andCheckSoftDeletionWithComma("")>
-<defaultOrderBy()>
+order by <recordIdField()> <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
index bece059..67c65f1 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
@@ -101,14 +101,14 @@ searchQuery(prefix) ::= <<
or <prefix>plugin_name like :likeSearchKey
>>
-getByPluginName() ::= <<
+getByPluginName(ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
where t.plugin_name = :pluginName
<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
-order by t.record_id
+order by t.record_id <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentSqlDao.sql.stg
index bf30477..b15a04b 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentSqlDao.sql.stg
@@ -82,7 +82,7 @@ searchQuery(prefix) ::= <<
or <prefix>external_key like :likeSearchKey
>>
-searchByState(states) ::= <<
+searchByState(states, ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
@@ -92,10 +92,10 @@ join (
where state_name in (<states: {state | :state_<i0>}; separator="," >)
<AND_CHECK_TENANT()>
<andCheckSoftDeletionWithComma()>
- order by <recordIdField()>
+ order by <recordIdField()> <ordering>
limit :rowCount offset :offset
) optimization on <recordIdField("optimization.")> = <recordIdField("t.")>
-order by <recordIdField("t.")>
+order by <recordIdField("t.")> <ordering>
;
>>
@@ -109,14 +109,14 @@ where t.state_name in (<states: {state | :state_<i0>}; separator="," >)
;
>>
-getByPluginName() ::= <<
+getByPluginName(ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
join payment_methods pm on pm.id = t.payment_method_id
where pm.plugin_name = :pluginName
<AND_CHECK_TENANT("t.")>
-order by t.record_id asc
+order by t.record_id <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/TransactionSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/TransactionSqlDao.sql.stg
index c00aee0..1f19f0b 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/TransactionSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/TransactionSqlDao.sql.stg
@@ -83,14 +83,14 @@ where payment_id = :paymentId
/* Does not include AND_CHECK_TENANT() since this is a global operation */
-getByTransactionStatusPriorDateAcrossTenants(statuses) ::= <<
+getByTransactionStatusPriorDateAcrossTenants(statuses, ordering) ::= <<
select <allTableFields()>
from <tableName()>
where
created_date >= :createdAfterDate
and created_date \< :createdBeforeDate
and transaction_status in (<statuses: {status | :status_<i0>}; separator="," >)
-<defaultOrderBy()>
+order by <recordIdField()> <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
index 9bbc75d..af140fb 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/engine/dao/DefaultSubscriptionDao.java
@@ -82,6 +82,7 @@ import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.billing.util.entity.Entity;
import org.killbill.billing.util.entity.Pagination;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
import org.killbill.billing.util.entity.dao.EntityDaoBase;
import org.killbill.billing.util.entity.dao.EntitySqlDao;
@@ -97,7 +98,6 @@ import org.killbill.notificationq.api.NotificationQueue;
import org.killbill.notificationq.api.NotificationQueueService;
import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue;
import org.skife.jdbi.v2.IDBI;
-import org.skife.jdbi.v2.sqlobject.customizers.OverrideStatementLocatorWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -206,8 +206,8 @@ public class DefaultSubscriptionDao extends EntityDaoBase<SubscriptionBundleMode
}
@Override
- public Iterator<SubscriptionBundleModelDao> build(final BundleSqlDao bundleSqlDao, final Long limit, final InternalTenantContext context) {
- return bundleSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ public Iterator<SubscriptionBundleModelDao> build(final BundleSqlDao bundleSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return bundleSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
}
},
offset,
diff --git a/util/src/main/java/org/killbill/billing/util/customfield/dao/DefaultCustomFieldDao.java b/util/src/main/java/org/killbill/billing/util/customfield/dao/DefaultCustomFieldDao.java
index 6561b8f..742bf5d 100644
--- a/util/src/main/java/org/killbill/billing/util/customfield/dao/DefaultCustomFieldDao.java
+++ b/util/src/main/java/org/killbill/billing/util/customfield/dao/DefaultCustomFieldDao.java
@@ -25,6 +25,7 @@ import java.util.UUID;
import javax.annotation.Nullable;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -161,8 +162,8 @@ public class DefaultCustomFieldDao extends EntityDaoBase<CustomFieldModelDao, Cu
}
@Override
- public Iterator<CustomFieldModelDao> build(final CustomFieldSqlDao customFieldSqlDao, final Long limit, final InternalTenantContext context) {
- return customFieldSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ public Iterator<CustomFieldModelDao> build(final CustomFieldSqlDao customFieldSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return customFieldSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
}
},
offset,
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
index 79bc6c9..574d3b0 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
@@ -29,6 +29,11 @@ import org.killbill.billing.util.entity.Pagination;
public class DefaultPaginationSqlDaoHelper {
+ // Number large enough so that small installations have access to an accurate count
+ // but small enough to not impact very large deployments
+ // TODO Should this be configurable per tenant?
+ private static final Long SIMPLE_PAGINATION_THRESHOLD = 20000L;
+
private final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao;
public DefaultPaginationSqlDaoHelper(final EntitySqlDaoTransactionalJdbiWrapper transactionalSqlDao) {
@@ -38,8 +43,13 @@ public class DefaultPaginationSqlDaoHelper {
public <E extends Entity, M extends EntityModelDao<E>, S extends EntitySqlDao<M, E>> Pagination<M> getPagination(final Class<? extends EntitySqlDao<M, E>> sqlDaoClazz,
final PaginationIteratorBuilder<M, E, S> paginationIteratorBuilder,
final Long offset,
- final Long limit,
+ final Long limitMaybeNegative,
@Nullable final InternalTenantContext context) {
+ // Use a negative limit as a hint to go backwards. It's a bit awkward -- using a negative offset instead would be more intuitive,
+ // but it is non-deterministic for the first page unfortunately (limit 0 offset 50: ASC or DESC?)
+ final Ordering ordering = limitMaybeNegative >= 0 ? Ordering.ASC : Ordering.DESC;
+ final Long limit = Math.abs(limitMaybeNegative);
+
// Note: the connection will be busy as we stream the results out: hence we cannot use
// SQL_CALC_FOUND_ROWS / FOUND_ROWS on the actual query.
// We still need to know the actual number of results, mainly for the UI so that it knows if it needs to fetch
@@ -56,8 +66,16 @@ public class DefaultPaginationSqlDaoHelper {
// We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here.
// Since we want to stream the results out, we don't want to auto-commit when this method returns.
final EntitySqlDao<M, E> sqlDao = transactionalSqlDao.onDemandForStreamingResults(sqlDaoClazz);
- final Long maxNbRecords = context != null ? sqlDao.getCount(context) : null;
- final Iterator<M> results = paginationIteratorBuilder.build((S) sqlDao, limit, context);
+ // The count to get maxNbRecords can be expensive on very large datasets. As a heuristic to check how large that number is,
+ // we retrieve 1 record at offset SIMPLE_PAGINATION_THRESHOLD (pretty fast). If we've found a record, that means the count is larger
+ // than this threshold and we don't issue the full count query
+ final Long maxNbRecords;
+ if (context == null || paginationIteratorBuilder.build((S) sqlDao, SIMPLE_PAGINATION_THRESHOLD, 1L, ordering, context).hasNext()) {
+ maxNbRecords = null;
+ } else {
+ maxNbRecords = sqlDao.getCount(context);
+ }
+ final Iterator<M> results = paginationIteratorBuilder.build((S) sqlDao, offset, limit, ordering, context);
final Long totalNbRecords = totalNbRecordsOrNull == null ? maxNbRecords : totalNbRecordsOrNull;
@@ -71,6 +89,11 @@ public class DefaultPaginationSqlDaoHelper {
// - For get calls, return the total number of records (totalNbRecords == maxNbRecords)
public abstract Long getCount(final S sqlDao, final InternalTenantContext context);
- public abstract Iterator<M> build(final S sqlDao, final Long limit, final InternalTenantContext context);
+ public abstract Iterator<M> build(final S sqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context);
+ }
+
+ public enum Ordering {
+ ASC,
+ DESC
}
}
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
index dbcfd7c..32ad513 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntityDaoBase.java
@@ -26,6 +26,7 @@ import org.killbill.billing.util.audit.ChangeType;
import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Entity;
import org.killbill.billing.util.entity.Pagination;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.PaginationIteratorBuilder;
public abstract class EntityDaoBase<M extends EntityModelDao<E>, E extends Entity, U extends BillingExceptionBase> implements EntityDao<M, E, U> {
@@ -142,8 +143,8 @@ public abstract class EntityDaoBase<M extends EntityModelDao<E>, E extends Entit
}
@Override
- public Iterator<M> build(final EntitySqlDao<M, E> sqlDao, final Long limit, final InternalTenantContext context) {
- return sqlDao.get(offset, limit, getNaturalOrderingColumns(), context);
+ public Iterator<M> build(final EntitySqlDao<M, E> sqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return sqlDao.get(offset, limit, getNaturalOrderingColumns(), ordering.toString(), context);
}
},
offset,
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
index b5aa2a0..d20a5e7 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/EntitySqlDao.java
@@ -73,6 +73,7 @@ public interface EntitySqlDao<M extends EntityModelDao<E>, E extends Entity> ext
@Bind("likeSearchKey") final String likeSearchKey,
@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
+ @Define("ordering") final String ordering,
@BindBean final InternalTenantContext context);
@SqlQuery
@@ -89,6 +90,7 @@ public interface EntitySqlDao<M extends EntityModelDao<E>, E extends Entity> ext
public Iterator<M> get(@Bind("offset") final Long offset,
@Bind("rowCount") final Long rowCount,
@Define("orderBy") final String orderBy,
+ @Define("ordering") final String ordering,
@BindBean final InternalTenantContext context);
@SqlQuery
diff --git a/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java b/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
index 81401d6..bdd5e16 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
@@ -67,7 +67,8 @@ public class DefaultPagination<T> implements Pagination<T> {
@Nullable final Long totalNbRecords, @Nullable final Long maxNbRecords,
final Iterator<T> delegateIterator) {
this.currentOffset = currentOffset;
- this.limit = limit;
+ // See DefaultPaginationSqlDaoHelper
+ this.limit = Math.abs(limit);
this.totalNbRecords = totalNbRecords;
this.maxNbRecords = maxNbRecords;
this.delegateIterator = delegateIterator;
diff --git a/util/src/main/java/org/killbill/billing/util/tag/dao/DefaultTagDao.java b/util/src/main/java/org/killbill/billing/util/tag/dao/DefaultTagDao.java
index 1b4c9ec..b6342ee 100644
--- a/util/src/main/java/org/killbill/billing/util/tag/dao/DefaultTagDao.java
+++ b/util/src/main/java/org/killbill/billing/util/tag/dao/DefaultTagDao.java
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.UUID;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
+import org.killbill.billing.util.entity.dao.DefaultPaginationSqlDaoHelper.Ordering;
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -224,8 +225,8 @@ public class DefaultTagDao extends EntityDaoBase<TagModelDao, Tag, TagApiExcepti
}
@Override
- public Iterator<TagModelDao> build(final TagSqlDao tagSqlDao, final Long limit, final InternalTenantContext context) {
- return tagSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, context);
+ public Iterator<TagModelDao> build(final TagSqlDao tagSqlDao, final Long offset, final Long limit, final Ordering ordering, final InternalTenantContext context) {
+ return tagSqlDao.search(searchKey, String.format("%%%s%%", searchKey), offset, limit, ordering.toString(), context);
}
},
offset,
diff --git a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
index 6f35450..a79883d 100644
--- a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -147,7 +147,7 @@ where <CHECK_TENANT("t.")>
;
>>
-get(offset, rowCount, orderBy) ::= <<
+get(offset, rowCount, orderBy, ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
@@ -156,10 +156,10 @@ join (
from <tableName()>
where <CHECK_TENANT()>
<andCheckSoftDeletionWithComma()>
- order by <orderBy>
+ order by <orderBy> <ordering>
limit :rowCount offset :offset
) optimization on <recordIdField("optimization.")> = <recordIdField("t.")>
-order by t.<orderBy>
+order by t.<orderBy> <ordering>
;
>>
@@ -268,14 +268,14 @@ searchQuery(prefix) ::= <<
1 = 1
>>
-search() ::= <<
+search(ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
where (<searchQuery("t.")>)
<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
-order by <recordIdField("t.")> ASC
+order by <recordIdField("t.")> <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
index 3240d91..177ec5b 100644
--- a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -114,7 +114,7 @@ searchQuery(tagAlias, tagDefinitionAlias) ::= <<
or <tagDefinitionAlias>description like :likeSearchKey
>>
-search() ::= <<
+search(ordering) ::= <<
select
<allTableFields("t.")>
from <tableName()> t
@@ -122,7 +122,7 @@ join (<userAndSystemTagDefinitions()>) td on td.id = t.tag_definition_id
where (<searchQuery(tagAlias="t.", tagDefinitionAlias="td.")>)
<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
-order by <recordIdField("t.")> ASC
+order by <recordIdField("t.")> <ordering>
limit :rowCount offset :offset
;
>>
diff --git a/util/src/test/java/org/killbill/billing/util/dao/TestPagination.java b/util/src/test/java/org/killbill/billing/util/dao/TestPagination.java
index 502ecfd..107585e 100644
--- a/util/src/test/java/org/killbill/billing/util/dao/TestPagination.java
+++ b/util/src/test/java/org/killbill/billing/util/dao/TestPagination.java
@@ -44,12 +44,12 @@ public class TestPagination extends UtilTestSuiteWithEmbeddedDB {
// Tests via SQL dao directly
Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.getAll(internalCallContext)).size(), 10);
- Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, 100L, "record_id", internalCallContext)).size(), 10);
- Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(5L, 100L, "record_id", internalCallContext)).size(), 5);
- Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(5L, 10L, "record_id", internalCallContext)).size(), 5);
- Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, 5L, "record_id", internalCallContext)).size(), 5);
+ Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, 100L, "record_id", "asc", internalCallContext)).size(), 10);
+ Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(5L, 100L, "record_id", "asc", internalCallContext)).size(), 5);
+ Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(5L, 10L, "record_id", "asc", internalCallContext)).size(), 5);
+ Assert.assertEquals(ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, 5L, "record_id", "asc", internalCallContext)).size(), 5);
for (int i = 0; i < 10; i++) {
- final List<TagDefinitionModelDao> tagDefinitions = ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, (long) i, "record_id", internalCallContext));
+ final List<TagDefinitionModelDao> tagDefinitions = ImmutableList.<TagDefinitionModelDao>copyOf(tagDefinitionSqlDao.get(0L, (long) i, "record_id", "asc", internalCallContext));
Assert.assertEquals(tagDefinitions.size(), i);
for (int j = 0; j < tagDefinitions.size(); j++) {
diff --git a/util/src/test/java/org/killbill/billing/util/dao/TestStringTemplateInheritance.java b/util/src/test/java/org/killbill/billing/util/dao/TestStringTemplateInheritance.java
index cc50c48..a93add6 100644
--- a/util/src/test/java/org/killbill/billing/util/dao/TestStringTemplateInheritance.java
+++ b/util/src/test/java/org/killbill/billing/util/dao/TestStringTemplateInheritance.java
@@ -114,24 +114,24 @@ public class TestStringTemplateInheritance extends UtilTestSuiteNoDB {
"where t.tenant_record_id = :tenantRecordId\r?\n" +
"order by t.record_id ASC\r?\n" +
";");
- assertPattern(kombucha.getInstanceOf("get", ImmutableMap.<String, String>of("orderBy", "record_id", "offset", "3", "rowCount", "12")).toString(), "select\r?\n" +
- " t.record_id\r?\n" +
- ", t.id\r?\n" +
- ", t.tea\r?\n" +
- ", t.mushroom\r?\n" +
- ", t.sugar\r?\n" +
- ", t.account_record_id\r?\n" +
- ", t.tenant_record_id\r?\n" +
- "from kombucha t\r?\n" +
- "join \\(\r?\n" +
- " select record_id\r?\n" +
- " from kombucha\r?\n" +
- " where tenant_record_id = :tenantRecordId\r?\n" +
- " order by record_id\r?\n" +
- " limit :rowCount offset :offset\r?\n" +
- "\\) optimization on optimization.record_id = t.record_id\r?\n" +
- "order by t.record_id\r?\n" +
- ";");
+ assertPattern(kombucha.getInstanceOf("get", ImmutableMap.<String, String>of("orderBy", "record_id", "offset", "3", "rowCount", "12", "ordering", "ASC")).toString(), "select\r?\n" +
+ " t.record_id\r?\n" +
+ ", t.id\r?\n" +
+ ", t.tea\r?\n" +
+ ", t.mushroom\r?\n" +
+ ", t.sugar\r?\n" +
+ ", t.account_record_id\r?\n" +
+ ", t.tenant_record_id\r?\n" +
+ "from kombucha t\r?\n" +
+ "join \\(\r?\n" +
+ " select record_id\r?\n" +
+ " from kombucha\r?\n" +
+ " where tenant_record_id = :tenantRecordId\r?\n" +
+ " order by record_id ASC\r?\n" +
+ " limit :rowCount offset :offset\r?\n" +
+ "\\) optimization on optimization.record_id = t.record_id\r?\n" +
+ "order by t.record_id ASC\r?\n" +
+ ";");
assertPattern(kombucha.getInstanceOf("test").toString(), "select\r?\n" +
" t.record_id\r?\n" +
", t.id\r?\n" +