From 70e2b1c2aed9c3264fd8a9aef5c8a36a61486609 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Thu, 29 Nov 2018 09:54:24 +1300 Subject: [PATCH] #1562 - Query cache use incorrect with RawExpression - incorrect bind hash --- .../server/expression/RawExpression.java | 6 +- .../server/expression/RawExpressionTest.java | 23 ++++++++ .../tests/cache/TestQueryCacheCountry.java | 58 +++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/main/java/io/ebeaninternal/server/expression/RawExpression.java b/src/main/java/io/ebeaninternal/server/expression/RawExpression.java index 85b593521..cad8582bd 100644 --- a/src/main/java/io/ebeaninternal/server/expression/RawExpression.java +++ b/src/main/java/io/ebeaninternal/server/expression/RawExpression.java @@ -74,7 +74,11 @@ class RawExpression extends NonPrepareExpression { @Override public int queryBindHash() { - return sql.hashCode(); + int hc = sql.hashCode(); + for (Object value : values) { + hc = hc * 92821 + value.hashCode(); + } + return hc; } @Override diff --git a/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java b/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java index c34e9c037..853a6a2c8 100644 --- a/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java +++ b/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java @@ -45,4 +45,27 @@ public class RawExpressionTest extends BaseExpressionTest { assertThat(exp("a", 10, 20).isSameByBind(exp("a", 10))).isFalse(); } + @Test + public void queryBindHash_when_sameBindValues() { + assert_queryBindHash_isSame(exp("a", 10), exp("a", 10)); + } + + @Test + public void queryBindHash_when_diffBindValues() { + assert_queryBindHash_isDifferent(exp("a", 10), exp("a", 20)); + } + + @Test + public void queryBindHash_when_diffBindValues2() { + assert_queryBindHash_isDifferent(exp("a", 10), exp("a", 10, 11)); + } + + public void assert_queryBindHash_isDifferent(RawExpression exp0, RawExpression exp1) { + assertThat(exp0.queryBindHash()).isNotEqualTo(exp1.queryBindHash()); + } + + public void assert_queryBindHash_isSame(RawExpression exp0, RawExpression exp1) { + assertThat(exp0.queryBindHash()).isEqualTo(exp1.queryBindHash()); + } + } diff --git a/src/test/java/org/tests/cache/TestQueryCacheCountry.java b/src/test/java/org/tests/cache/TestQueryCacheCountry.java index b70a8ad81..28694eac3 100644 --- a/src/test/java/org/tests/cache/TestQueryCacheCountry.java +++ b/src/test/java/org/tests/cache/TestQueryCacheCountry.java @@ -62,6 +62,60 @@ public class TestQueryCacheCountry extends BaseTestCase { assertEquals(1, queryStats1.getHitCount()); } + @Test + public void rawExpression() { + + ResetBasicData.reset(); + awaitL2Cache(); + clearCache(); + + List countryList0 = Ebean.find(Country.class) + .setUseQueryCache(true) + .where().raw("code = ?", "NZ") + .findList(); + + assertThat(countryList0.get(0).getName()).isEqualTo("New Zealand"); + + List countryList1 = Ebean.find(Country.class) + .setUseQueryCache(true) + .where().raw("code = ?", "AU") + .findList(); + + assertThat(countryList1.get(0).getName()).isEqualTo("Australia"); + + ServerCacheStatistics queryStats1 = queryCache.getStatistics(false); + assertEquals(2, queryStats1.getMissCount()); + assertEquals(2, queryStats1.getSize()); + assertEquals(0, queryStats1.getHitCount()); // no hits yet + + + // we get a hit this time + List countryList2 = Ebean.find(Country.class) + .setUseQueryCache(true) + .where().raw("code = ?", "NZ") + .findList(); + + assertThat(countryList2.get(0).getName()).isEqualTo("New Zealand"); + + ServerCacheStatistics queryStats2 = queryCache.getStatistics(false); + assertEquals(2, queryStats2.getMissCount()); + assertEquals(2, queryStats2.getSize()); + assertEquals(1, queryStats2.getHitCount()); // got a hit + + // we get a hit on AU + List countryList3 = Ebean.find(Country.class) + .setUseQueryCache(true) + .where().raw("code = ?", "AU") + .findList(); + + assertThat(countryList3.get(0).getName()).isEqualTo("Australia"); + + ServerCacheStatistics queryStats3 = queryCache.getStatistics(false); + assertEquals(2, queryStats3.getMissCount()); + assertEquals(2, queryStats3.getSize()); + assertEquals(2, queryStats3.getHitCount()); // got another hit + } + @Test public void test() { @@ -104,6 +158,10 @@ public class TestQueryCacheCountry extends BaseTestCase { .findList(); assertNotSame(countryList2, countryList0); + + nz = Ebean.find(Country.class, "NZ"); + nz.setName("New Zealand"); + Ebean.save(nz); } }