diff --git a/ebean-api/src/main/java/io/ebean/ProfileLocation.java b/ebean-api/src/main/java/io/ebean/ProfileLocation.java index 605de580a..33584a0b3 100644 --- a/ebean-api/src/main/java/io/ebean/ProfileLocation.java +++ b/ebean-api/src/main/java/io/ebean/ProfileLocation.java @@ -45,14 +45,6 @@ public interface ProfileLocation { */ String label(); - /** - * Return a hash of the location that intentionally excludes the line number. - *

- * The hash is expected to be stable regardless of line number in the source file - * so that is identifies the class and method location over a long time. - */ - long hash(); - /** * Return the full location. */ diff --git a/ebean-api/src/main/java/io/ebean/meta/MetaQueryMetric.java b/ebean-api/src/main/java/io/ebean/meta/MetaQueryMetric.java index f5fee986c..1c9b5fe12 100644 --- a/ebean-api/src/main/java/io/ebean/meta/MetaQueryMetric.java +++ b/ebean-api/src/main/java/io/ebean/meta/MetaQueryMetric.java @@ -45,15 +45,8 @@ public interface MetaQueryMetric extends MetaTimedMetric { } /** - * Return the hash of the sql. + * Return the hash of the plan. */ - long sqlHash(); + String hash(); - /** - * Migrate to sqlHash(). - */ - @Deprecated - default long getSqlHash() { - return sqlHash(); - } } diff --git a/ebean-api/src/main/java/io/ebean/meta/MetaQueryPlan.java b/ebean-api/src/main/java/io/ebean/meta/MetaQueryPlan.java index 6cdce69a1..c1ae44a82 100644 --- a/ebean-api/src/main/java/io/ebean/meta/MetaQueryPlan.java +++ b/ebean-api/src/main/java/io/ebean/meta/MetaQueryPlan.java @@ -30,7 +30,7 @@ public interface MetaQueryPlan { /** * Return the hash of the plan. */ - long sqlHash(); + String hash(); /** * Return a description of the bind values. diff --git a/ebean-api/src/main/java/io/ebean/meta/MetaTimedMetric.java b/ebean-api/src/main/java/io/ebean/meta/MetaTimedMetric.java index dbd0f0a0e..f95f3248d 100644 --- a/ebean-api/src/main/java/io/ebean/meta/MetaTimedMetric.java +++ b/ebean-api/src/main/java/io/ebean/meta/MetaTimedMetric.java @@ -6,14 +6,6 @@ package io.ebean.meta; */ public interface MetaTimedMetric extends MetaMetric { - /** - * Return the metric location hash if defined. - *

- * This hash excludes line number with the intention of being stable over time - * as code changes move the source line (but the method is the same). - */ - long locationHash(); - /** * Return the metric location if defined. */ diff --git a/ebean-api/src/main/java/io/ebean/meta/MetricData.java b/ebean-api/src/main/java/io/ebean/meta/MetricData.java index 7f2eb38b6..b4606b1d7 100644 --- a/ebean-api/src/main/java/io/ebean/meta/MetricData.java +++ b/ebean-api/src/main/java/io/ebean/meta/MetricData.java @@ -6,7 +6,7 @@ package io.ebean.meta; public class MetricData { private String name; - private long sqlHash; + private String hash; private String loc; private String sql; @@ -14,7 +14,6 @@ public class MetricData { private Long mean; private Long max; private Long total; - private long locHash; public MetricData(String name) { this.name = name; @@ -31,20 +30,12 @@ public class MetricData { this.name = name; } - public long getSqlHash() { - return sqlHash; + public String getHash() { + return hash; } - public void setSqlHash(long sqlHash) { - this.sqlHash = sqlHash; - } - - public void setLocHash(long locHash) { - this.locHash = locHash; - } - - public long getLocHash() { - return locHash; + public void setHash(String hash) { + this.hash = hash; } public String getLoc() { diff --git a/ebean-api/src/main/java/io/ebean/meta/QueryPlanInit.java b/ebean-api/src/main/java/io/ebean/meta/QueryPlanInit.java index 7caeabd2f..5cce68994 100644 --- a/ebean-api/src/main/java/io/ebean/meta/QueryPlanInit.java +++ b/ebean-api/src/main/java/io/ebean/meta/QueryPlanInit.java @@ -10,7 +10,7 @@ public class QueryPlanInit { private boolean all; - private Set hashes = new HashSet<>(); + private Set hashes = new HashSet<>(); private long thresholdMicros; @@ -47,21 +47,21 @@ public class QueryPlanInit { /** * Return true if the query plan should be initiated based on it's hash. */ - public boolean includeHash(long sqlHash) { - return all || hashes.contains(sqlHash); + public boolean includeHash(String hash) { + return all || hashes.contains(hash); } /** * Return the specific hashes that we want to collect query plans on. */ - public Set sqlHashes() { + public Set hashes() { return hashes; } /** * Set the specific hashes that we want to collect query plans on. */ - public void sqlHashes(Set hashes) { + public void hashes(Set hashes) { this.hashes = hashes; } } diff --git a/ebean-api/src/main/java/io/ebean/metric/TimedMetricStats.java b/ebean-api/src/main/java/io/ebean/metric/TimedMetricStats.java index 8c88d839e..3012e9e9f 100644 --- a/ebean-api/src/main/java/io/ebean/metric/TimedMetricStats.java +++ b/ebean-api/src/main/java/io/ebean/metric/TimedMetricStats.java @@ -12,11 +12,6 @@ public interface TimedMetricStats extends MetaTimedMetric { */ void setLocation(String location); - /** - * Additionally set the location hash. - */ - void setLocationHash(long locationHash); - /** * Override the name based on profile location. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQueryPlan.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQueryPlan.java index 878dcc716..0b4c3ea0a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQueryPlan.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQueryPlan.java @@ -20,7 +20,7 @@ public interface SpiQueryPlan { /** * The hash of the sql. */ - long getSqlHash(); + String getHash(); /** * The SQL for the query plan. diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetrics.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetrics.java index 968e96a98..5274b4ced 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetrics.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetrics.java @@ -120,7 +120,7 @@ class DumpMetrics { appendQueryName(metric, sb); appendCounters(metric, sb); if (dumpHash) { - sb.append("\n sqlHash:").append(metric.sqlHash()); + sb.append("\n hash:").append(metric.hash()); } appendProfileAndSql(metric, sb); out(sb.toString()); @@ -134,7 +134,6 @@ class DumpMetrics { String location = metric.location(); if (dumpLoc && location != null) { sb.append("\n loc:").append(location); - sb.append("\n locHash:").append(metric.locationHash()); } if (dumpSql) { sb.append(" \n\n sql:").append(metric.sql()).append("\n\n"); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsData.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsData.java index 07980228f..4bc1e5035 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsData.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsData.java @@ -56,7 +56,6 @@ class DumpMetricsData { final MetricData data = create(metric); appendCounters(data, metric); data.setLoc(metric.location()); - data.setLocHash(metric.locationHash()); } private void addCount(MetaCountMetric metric) { @@ -68,11 +67,10 @@ class DumpMetricsData { final MetricData data = create(metric); appendCounters(data, metric); appendLocationAndSql(data, metric); - data.setSqlHash(metric.sqlHash()); + data.setHash(metric.hash()); } private void appendLocationAndSql(MetricData data, MetaQueryMetric metric) { - data.setLocHash(metric.locationHash()); data.setLoc(metric.location()); data.setSql(metric.sql()); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java index c116ebd26..90200f79b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DumpMetricsJson.java @@ -188,8 +188,7 @@ class DumpMetricsJson implements ServerMetricsAsJson { metricStart(metric); appendTiming(metric); if (isIncludeDetail(metric)) { - keyVal("locHash", metric.locationHash()); - appendExtra("loc", metric.location()); + append("loc", metric.location()); } metricEnd(); } @@ -198,12 +197,11 @@ class DumpMetricsJson implements ServerMetricsAsJson { metricStart(metric); appendTiming(metric); if (withHash) { - keyVal("sqlHash", metric.sqlHash()); - keyVal("locHash", metric.locationHash()); + append("hash", metric.hash()); } if (isIncludeDetail(metric)) { - appendExtra("loc", metric.location()); - appendExtra("sql", metric.sql()); + append("loc", metric.location()); + append("sql", metric.sql()); } metricEnd(); } @@ -212,7 +210,7 @@ class DumpMetricsJson implements ServerMetricsAsJson { return includeExtraAttributes == 2 || includeExtraAttributes == 1 && metric.initialCollection(); } - private void appendExtra(String key, String val) throws IOException { + private void append(String key, String val) throws IOException { if (val != null) { key(key); val(val); @@ -220,13 +218,13 @@ class DumpMetricsJson implements ServerMetricsAsJson { } private void appendTiming(MetaTimedMetric timedMetric) throws IOException { - keyVal("count", timedMetric.count()); - keyVal("total", timedMetric.total()); - keyVal("mean", timedMetric.mean()); - keyVal("max", timedMetric.max()); + append("count", timedMetric.count()); + append("total", timedMetric.total()); + append("mean", timedMetric.mean()); + append("max", timedMetric.max()); } - private void keyVal(String key, long value) throws IOException { + private void append(String key, long value) throws IOException { key(key); val(value); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java index 6a9acd839..8e8b02b6f 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanDescriptor.java @@ -1558,7 +1558,7 @@ public class BeanDescriptor implements BeanType, STreeType, SpiBeanType { void queryPlanInit(QueryPlanInit request, List list) { for (CQueryPlan queryPlan : queryPlanCache.values()) { - if (request.includeHash(queryPlan.getSqlHash())) { + if (request.includeHash(queryPlan.getHash())) { queryPlan.queryPlanInit(request.thresholdMicros()); list.add(queryPlan.createMeta(null, null)); } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/BasicProfileLocation.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/BasicProfileLocation.java index 8e8a5ffc0..d7d5b0fd2 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/BasicProfileLocation.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/BasicProfileLocation.java @@ -10,12 +10,10 @@ final class BasicProfileLocation implements ProfileLocation { private final String fullLocation; private final String location; private final String label; - private final long hash; BasicProfileLocation(String fullLocation) { this.fullLocation = fullLocation; - this.hash = UtilLocation.hash(fullLocation); - this.location = shortDesc(fullLocation); + this.location = UtilLocation.loc(fullLocation); this.label = UtilLocation.label(location); } @@ -44,11 +42,6 @@ final class BasicProfileLocation implements ProfileLocation { return location; } - @Override - public long hash() { - return hash; - } - @Override public String fullLocation() { return fullLocation; @@ -64,15 +57,4 @@ final class BasicProfileLocation implements ProfileLocation { // do nothing } - private String shortDesc(String location) { - int lastPer = location.lastIndexOf('.'); - if (lastPer > -1) { - lastPer = location.lastIndexOf('.', lastPer - 1); - if (lastPer > -1) { - return location.substring(lastPer + 1); - } - } - return location; - } - } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DProfileLocation.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DProfileLocation.java index 9c6340ad4..63fa0e11a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DProfileLocation.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DProfileLocation.java @@ -13,7 +13,6 @@ class DProfileLocation implements ProfileLocation { private String fullLocation; private String location; private String label; - private long hash; private final int lineNumber; private int traceCount; @@ -46,11 +45,10 @@ class DProfileLocation implements ProfileLocation { return false; } final String loc = create(); - final String shortDesc = shortDesc(loc); - label = UtilLocation.label(shortDesc); - location = shortDesc; - fullLocation = loc; - hash = UtilLocation.hash(loc); + final String location = UtilLocation.loc(loc); + this.label = UtilLocation.label(location); + this.location = location; + this.fullLocation = loc; initWith(label); return true; } @@ -69,11 +67,6 @@ class DProfileLocation implements ProfileLocation { return location; } - @Override - public long hash() { - return hash; - } - @Override public String fullLocation() { return fullLocation; @@ -116,20 +109,4 @@ class DProfileLocation implements ProfileLocation { return traceLine.substring(0, traceLine.length() - 1) + ":" + lineNumber + ")"; } } - - private String shortDesc(String location) { - int pos = location.lastIndexOf('('); - if (pos == -1) { - pos = location.length(); - } - - pos = location.lastIndexOf('.', pos); - if (pos > -1) { - pos = location.lastIndexOf('.', pos - 1); - if (pos > -1) { - return location.substring(pos + 1); - } - } - return location; - } } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMeta.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMeta.java index 0354bbd0a..67f724051 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMeta.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMeta.java @@ -1,7 +1,7 @@ package io.ebeaninternal.server.profile; import io.ebean.ProfileLocation; -import io.ebeaninternal.server.util.Checksum; +import io.ebeaninternal.server.util.Md5; class DQueryPlanMeta { @@ -10,7 +10,7 @@ class DQueryPlanMeta { private final ProfileLocation profileLocation; private final String name; private final String sql; - private final long sqlHash; + private final String hash; DQueryPlanMeta(Class type, String label, ProfileLocation profileLocation, String sql) { this.type = type; @@ -22,15 +22,16 @@ class DQueryPlanMeta { name += "_" + label; } this.name = name; - this.sqlHash = Checksum.checksum(sql); + String loc = profileLocation == null ? null : profileLocation.location(); + this.hash = Md5.hash(sql, name, loc); } public Class getType() { return type; } - public long getSqlHash() { - return sqlHash; + public String getHash() { + return hash; } public String getName() { @@ -49,10 +50,6 @@ class DQueryPlanMeta { return (profileLocation == null) ? null : profileLocation.location(); } - public long getLocationHash() { - return (profileLocation == null) ? 0 : profileLocation.hash(); - } - public String getSql() { return sql; } diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMetric.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMetric.java index 41a0658f4..e24da73c7 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMetric.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DQueryPlanMetric.java @@ -59,8 +59,8 @@ class DQueryPlanMetric implements QueryPlanMetric { } @Override - public long sqlHash() { - return meta.getSqlHash(); + public String hash() { + return meta.getHash(); } @Override @@ -83,11 +83,6 @@ class DQueryPlanMetric implements QueryPlanMetric { return meta.getLocation(); } - @Override - public long locationHash() { - return meta.getLocationHash(); - } - @Override public long count() { return stats.count(); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DTimeMetricStats.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DTimeMetricStats.java index 82731dfd3..a4243e31a 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/DTimeMetricStats.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/DTimeMetricStats.java @@ -14,7 +14,6 @@ class DTimeMetricStats implements TimedMetricStats { private String name; private String location; - private long locationHash; DTimeMetricStats(String name, boolean collected, long count, long total, long max) { this.name = name; @@ -37,7 +36,6 @@ class DTimeMetricStats implements TimedMetricStats { .append(" max:").append(max); if (location != null) { sb.append(" loc:").append(location); - sb.append(" locHash:").append(locationHash); } return sb.toString(); } @@ -47,11 +45,6 @@ class DTimeMetricStats implements TimedMetricStats { this.location = location; } - @Override - public void setLocationHash(long locationHash) { - this.locationHash = locationHash; - } - @Override public boolean initialCollection() { return !collected; @@ -72,11 +65,6 @@ class DTimeMetricStats implements TimedMetricStats { return location; } - @Override - public long locationHash() { - return locationHash; - } - /** * Return the count of values collected. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/profile/UtilLocation.java b/ebean-core/src/main/java/io/ebeaninternal/server/profile/UtilLocation.java index 00b388bbd..65ab1ce4d 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/profile/UtilLocation.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/profile/UtilLocation.java @@ -1,28 +1,29 @@ package io.ebeaninternal.server.profile; -import io.ebeaninternal.server.util.Checksum; - final class UtilLocation { - /** - * Return a hash of the full description excluding the source line number. - */ - static long hash(String full) { + static String loc(String full) { final int pos = full.lastIndexOf('('); if (pos > -1) { - return Checksum.checksum(full.substring(0, pos)); + return full.substring(0, pos); } else { - return Checksum.checksum(full); + return full; } } - static String label(String shortDescription) { - int pos = shortDescription.indexOf("("); - if (pos == -1) { - return shortDescription; - } else { - return trimInit(shortDescription.substring(0, pos)); + static String label(String location) { + return trimInit(shortDesc(location)); + } + + private static String shortDesc(String location) { + int pos = location.lastIndexOf('.'); + if (pos > -1) { + pos = location.lastIndexOf('.', pos - 1); + if (pos > -1) { + return location.substring(pos + 1); + } } + return location; } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java index 770ac522d..de365f253 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java @@ -13,7 +13,7 @@ import io.ebeaninternal.api.SpiQueryBindCapture; import io.ebeaninternal.api.SpiQueryPlan; import io.ebeaninternal.server.core.OrmQueryRequest; import io.ebeaninternal.server.core.timezone.DataTimeZone; -import io.ebeaninternal.server.util.Checksum; +import io.ebeaninternal.server.util.Md5; import io.ebeaninternal.server.util.Str; import io.ebeaninternal.server.query.CQueryPlanStats.Snapshot; import io.ebeaninternal.server.type.DataBind; @@ -56,13 +56,12 @@ public class CQueryPlan implements SpiQueryPlan { private final SpiEbeanServer server; private final ProfileLocation profileLocation; private final String location; - private final long locationHash; private final String label; private final String name; private final CQueryPlanKey planKey; private final boolean rawSql; private final String sql; - private final long sqlHash; + private final String hash; private final String logWhereSql; private final SqlTree sqlTree; @@ -93,7 +92,6 @@ public class CQueryPlan implements SpiQueryPlan { SpiQuery query = request.getQuery(); this.profileLocation = query.getProfileLocation(); this.location = (profileLocation == null) ? null : profileLocation.location(); - this.locationHash = (profileLocation == null) ? 0 : profileLocation.hash(); this.label = query.getPlanLabel(); this.name = deriveName(label, query.getType(), request.getBeanDescriptor().getSimpleName()); this.asOfTableCount = query.getAsOfTableCount(); @@ -105,7 +103,7 @@ public class CQueryPlan implements SpiQueryPlan { this.stats = new CQueryPlanStats(this); this.dependentTables = sqlTree.dependentTables(); this.bindCapture = initBindCapture(query); - this.sqlHash = Checksum.checksum(sql); + this.hash = Md5.hash(sql, name, location); } /** @@ -118,7 +116,6 @@ public class CQueryPlan implements SpiQueryPlan { SpiQuery query = request.getQuery(); this.profileLocation = query.getProfileLocation(); this.location = (profileLocation == null) ? null : profileLocation.location(); - this.locationHash = (profileLocation == null) ? 0 : profileLocation.hash(); this.label = query.getPlanLabel(); this.name = deriveName(label, query.getType(), request.getBeanDescriptor().getSimpleName()); this.planKey = buildPlanKey(sql, logWhereSql); @@ -131,7 +128,7 @@ public class CQueryPlan implements SpiQueryPlan { this.stats = new CQueryPlanStats(this); this.dependentTables = sqlTree.dependentTables(); this.bindCapture = initBindCaptureRaw(sql, query); - this.sqlHash = Checksum.checksum(sql); + this.hash = Md5.hash(sql, name, location); } private String deriveName(String label, SpiQuery.Type type, String simpleName) { @@ -177,8 +174,8 @@ public class CQueryPlan implements SpiQueryPlan { } @Override - public long getSqlHash() { - return sqlHash; + public String getHash() { + return hash; } @Override @@ -203,10 +200,6 @@ public class CQueryPlan implements SpiQueryPlan { return location; } - public long getLocationHash() { - return locationHash; - } - @Override public void queryPlanInit(long thresholdMicros) { bindCapture.queryPlanInit(thresholdMicros); @@ -214,7 +207,7 @@ public class CQueryPlan implements SpiQueryPlan { @Override public DQueryPlanOutput createMeta(String bind, String planString) { - return new DQueryPlanOutput(getBeanType(), name, sqlHash, sql, profileLocation, bind, planString); + return new DQueryPlanOutput(getBeanType(), name, hash, sql, profileLocation, bind, planString); } public DataReader createDataReader(ResultSet rset) { @@ -261,7 +254,7 @@ public class CQueryPlan implements SpiQueryPlan { private String calcAuditQueryKey() { // rawSql needs to include the MD5 hash of the sql - return rawSql ? planKey.getPartialKey() + "_" + sqlHash : planKey.getPartialKey(); + return rawSql ? planKey.getPartialKey() + "_" + hash : planKey.getPartialKey(); } SqlTree getSqlTree() { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanStats.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanStats.java index ab7dc0b63..ffc749eb9 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanStats.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryPlanStats.java @@ -106,11 +106,6 @@ public final class CQueryPlanStats { return queryPlan.getLocation(); } - @Override - public long locationHash() { - return queryPlan.getLocationHash(); - } - @Override public long count() { return metrics.count(); @@ -132,8 +127,8 @@ public final class CQueryPlanStats { } @Override - public long sqlHash() { - return queryPlan.getSqlHash(); + public String hash() { + return queryPlan.getHash(); } @Override diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/DQueryPlanOutput.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/DQueryPlanOutput.java index 3d879362b..1c1a41d07 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/DQueryPlanOutput.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/DQueryPlanOutput.java @@ -16,14 +16,14 @@ class DQueryPlanOutput implements MetaQueryPlan, SpiDbQueryPlan { private final String sql; private final String bind; private final String plan; - private final long sqlHash; + private final String hash; private long queryTimeMicros; private long captureCount; - DQueryPlanOutput(Class beanType, String label, long sqlHash, String sql, ProfileLocation profileLocation, String bind, String plan) { + DQueryPlanOutput(Class beanType, String label, String hash, String sql, ProfileLocation profileLocation, String bind, String plan) { this.beanType = beanType; this.label = label; - this.sqlHash = sqlHash; + this.hash = hash; this.sql = sql; this.profileLocation = profileLocation; this.bind = bind; @@ -31,8 +31,8 @@ class DQueryPlanOutput implements MetaQueryPlan, SpiDbQueryPlan { } @Override - public long sqlHash() { - return sqlHash; + public String hash() { + return hash; } /** @@ -99,7 +99,7 @@ class DQueryPlanOutput implements MetaQueryPlan, SpiDbQueryPlan { @Override public String toString() { - return " BeanType:" + ((beanType == null) ? "" : beanType.getSimpleName()) + " planHash:" + sqlHash + " label:" + label + " queryTimeMicros:" + queryTimeMicros + " captureCount:" + captureCount + "\n SQL:" + sql + "\nBIND:" + bind + "\nPLAN:" + plan; + return " BeanType:" + ((beanType == null) ? "" : beanType.getSimpleName()) + " planHash:" + hash + " label:" + label + " queryTimeMicros:" + queryTimeMicros + " captureCount:" + captureCount + "\n SQL:" + sql + "\nBIND:" + bind + "\nPLAN:" + plan; } /** diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/util/Md5.java b/ebean-core/src/main/java/io/ebeaninternal/server/util/Md5.java new file mode 100644 index 000000000..45df901f0 --- /dev/null +++ b/ebean-core/src/main/java/io/ebeaninternal/server/util/Md5.java @@ -0,0 +1,36 @@ +package io.ebeaninternal.server.util; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; + +public final class Md5 { + + /** + * Return the MD5 hash of the underlying sql. + */ + public static String hash(String... values) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + for (String val : values) { + if (val != null) { + md.update(val.getBytes(StandardCharsets.UTF_8)); + } + } + return digestToHex(md.digest()); + } catch (Exception e) { + throw new RuntimeException("MD5 hashing failed", e); + } + } + + /** + * Convert the digest into a hex value. + */ + private static String digestToHex(byte[] digest) { + StringBuilder sb = new StringBuilder(32); + for (byte aDigest : digest) { + sb.append(Integer.toString((aDigest & 0xff) + 0x100, 16).substring(1)); + } + return sb.toString(); + } + +} diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/profile/BasicProfileLocationTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/profile/BasicProfileLocationTest.java index 6dfdad9f6..84a53442a 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/profile/BasicProfileLocationTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/profile/BasicProfileLocationTest.java @@ -14,7 +14,7 @@ public class BasicProfileLocationTest { assertThat(loc.obtain()).isTrue(); assertThat(loc.fullLocation()).endsWith(":12)"); - assertThat(loc.location()).isEqualTo("NativeMethodAccessorImpl.invoke0(Native Method:12)"); + assertThat(loc.location()).isEqualTo("java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0"); assertThat(loc.label()).isEqualTo("NativeMethodAccessorImpl.invoke0"); } @@ -24,7 +24,7 @@ public class BasicProfileLocationTest { BasicProfileLocation loc = new BasicProfileLocation("com.foo.Bar.all"); assertThat(loc.obtain()).isFalse(); assertThat(loc.fullLocation()).isEqualTo("com.foo.Bar.all"); - assertThat(loc.location()).isEqualTo("Bar.all"); + assertThat(loc.location()).isEqualTo("com.foo.Bar.all"); assertThat(loc.label()).isEqualTo("Bar.all"); } @@ -34,7 +34,7 @@ public class BasicProfileLocationTest { BasicProfileLocation loc = new BasicProfileLocation("foo.Bar.all"); assertThat(loc.obtain()).isFalse(); assertThat(loc.fullLocation()).isEqualTo("foo.Bar.all"); - assertThat(loc.location()).isEqualTo("Bar.all"); + assertThat(loc.location()).isEqualTo("foo.Bar.all"); assertThat(loc.label()).isEqualTo("Bar.all"); } } diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/profile/UtilLocationTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/profile/UtilLocationTest.java index 5fcbe90a4..0b26078ff 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/profile/UtilLocationTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/profile/UtilLocationTest.java @@ -9,13 +9,12 @@ public class UtilLocationTest { @Test public void label() { assertThat(UtilLocation.label("foo")).isEqualTo("foo"); - assertThat(UtilLocation.label("ProfileLocationTest$Other.(ProfileLocationTest.java:47)")).isEqualTo("ProfileLocationTest$Other.init"); + assertThat(UtilLocation.label("ProfileLocationTest$Other.")).isEqualTo("ProfileLocationTest$Other.init"); } @Test - public void hash() { - assertThat(UtilLocation.hash("org.foo.MyFoo.doIt(MyFoo.java:12)")).isEqualTo(396279222L); - assertThat(UtilLocation.hash("org.foo.MyFoo.doIt(MyFoo.java:13)")).isEqualTo(396279222L); - assertThat(UtilLocation.hash("org.foo.MyFoo.doIt(MyFoo.java:945)")).isEqualTo(396279222L); + public void loc() { + assertThat(UtilLocation.loc("org.foo.MyFoo.doIt(MyFoo.java:12)")).isEqualTo("org.foo.MyFoo.doIt"); + assertThat(UtilLocation.label("org.foo.MyFoo.doIt")).isEqualTo("MyFoo.doIt"); } } diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/util/Md5Test.java b/ebean-core/src/test/java/io/ebeaninternal/server/util/Md5Test.java new file mode 100644 index 000000000..9f0106cae --- /dev/null +++ b/ebean-core/src/test/java/io/ebeaninternal/server/util/Md5Test.java @@ -0,0 +1,53 @@ +package io.ebeaninternal.server.util; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class Md5Test { + + @Test + public void hash() throws Exception { + String content = "some random content we wish to hash"; + String hash1 = Md5.hash(content); + String hash2 = Md5.hash(content); + assertEquals(hash1, hash2); + assertEquals(hash1, "62c20bf679ff56cb746452ab5c88e3ed"); + } + + @Test + public void hashDifferent() throws Exception { + String hash1 = Md5.hash("one"); + String hash2 = Md5.hash("two"); + String hash3 = Md5.hash("onetwo"); + + assertNotEquals(hash1, hash2); + assertNotEquals(hash2, hash3); + assertEquals(hash1, "f97c5d29941bfb1b2fdab0874906ab82"); + } + + @Test + public void hashMulti() { + String hash1 = Md5.hash("one", "two"); + String hash2 = Md5.hash("onetwo"); + + assertEquals(hash1, hash2); + assertEquals(hash1, "5b9164ad6f496d9dee12ec7634ce253f"); + } + + @Test + public void hashMulti_when_null() { + String hash1 = Md5.hash("one", null); + String hash2 = Md5.hash("one"); + + assertEquals(hash1, hash2); + assertEquals(hash1, "f97c5d29941bfb1b2fdab0874906ab82"); + } + + @Test + public void when_null() { + String hash1 = Md5.hash(null, null); + assertEquals(hash1, "d41d8cd98f00b204e9800998ecf8427e"); + } +} diff --git a/ebean-core/src/test/java/org/tests/profile/ProfileLocationTest.java b/ebean-core/src/test/java/org/tests/profile/ProfileLocationTest.java index d452b7463..c7b0edfe9 100644 --- a/ebean-core/src/test/java/org/tests/profile/ProfileLocationTest.java +++ b/ebean-core/src/test/java/org/tests/profile/ProfileLocationTest.java @@ -20,15 +20,13 @@ public class ProfileLocationTest { public void test_obtain() { assertThat(doIt()).isTrue(); assertThat(loc.fullLocation()).isEqualTo("org.tests.profile.ProfileLocationTest.doIt(ProfileLocationTest.java:16)"); - assertThat(loc.location()).isEqualTo("ProfileLocationTest.doIt(ProfileLocationTest.java:16)"); + assertThat(loc.location()).isEqualTo("org.tests.profile.ProfileLocationTest.doIt"); assertThat(loc.label()).isEqualTo("ProfileLocationTest.doIt"); - assertThat(loc.hash()).isEqualTo(1867926812L); // same hash even when the line number has changed assertThat(locB.fullLocation()).isEqualTo("org.tests.profile.ProfileLocationTest.doIt(ProfileLocationTest.java:15)"); - assertThat(locB.location()).isEqualTo("ProfileLocationTest.doIt(ProfileLocationTest.java:15)"); + assertThat(locB.location()).isEqualTo("org.tests.profile.ProfileLocationTest.doIt"); assertThat(locB.label()).isEqualTo("ProfileLocationTest.doIt"); - assertThat(locB.hash()).isEqualTo(1867926812L); } @Test @@ -43,7 +41,7 @@ public class ProfileLocationTest { other.hashCode(); assertThat(loc2.label()).isEqualTo("ProfileLocationTest$Other.init"); - assertThat(loc2.location()).isEqualTo("ProfileLocationTest$Other.(ProfileLocationTest.java:52)"); + assertThat(loc2.location()).isEqualTo("org.tests.profile.ProfileLocationTest$Other."); } static class Other { diff --git a/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java b/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java index 6dfd99422..d36e36b51 100644 --- a/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java +++ b/ebean-core/src/test/java/org/tests/query/finder/TestCustomerFinder.java @@ -242,10 +242,9 @@ public class TestCustomerFinder extends BaseTestCase { assertThat(metricsJson).contains("\"name\":\"txn.main\""); assertThat(metricsJson).contains("\"name\":\"orm.Customer.findList\""); - assertThat(metricsJson).contains("\"locHash\":3254522637"); - assertThat(metricsJson).contains("\"loc\":\"CustomerFinder.byNameStatus(CustomerFinder.java:43)\""); + assertThat(metricsJson).contains("\"loc\":\"org.tests.model.basic.finder.CustomerFinder.byNameStatus\""); if (isH2() || isPostgres()) { - assertThat(metricsJson).contains("\"sqlHash\":3634991469"); + assertThat(metricsJson).contains("\"hash\":\"de3affa5b4bff07e19c1c012590dcde6\""); assertThat(metricsJson).contains("\"sql\":\"select t0.id, t0.status,"); } }