From f7eeabfa90e5ac105c0abc192669d6d05d90fb8a Mon Sep 17 00:00:00 2001 From: Tuukka Lehtonen Date: Sun, 26 Aug 2018 15:28:01 +0300 Subject: [PATCH] Backported b75a6bbc for release/1.35.0 Previous too-optimized implementation had multiple flaws: * Index calculation did not have enough parenthesis in it which meant that the value table index was sometimes calculated incorrectly. This lead to string literal values being read incorrectly. * Did not take into account string literals longer than 127 characters * Did not take into account that string literals are modified-utf-8 encoded and simply decoded them as US-ASCII bytes. Essentially all resources with name containing special characters were indexed incorrectly up until now. All of these flaws have been in the code for ages. gitlab #86 Change-Id: Ibd5ecbaa1cdd1b8be759905bd8c29b9f8e012207 (cherry picked from commit cd47b6877cee258113eb00523701a57374becfd8) --- .../internal/DirectQuerySupportImpl.java | 60 ++++++++++++------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java index 0b640861e..5f6c722ac 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/DirectQuerySupportImpl.java @@ -35,6 +35,13 @@ import org.simantics.db.service.DirectQuerySupport; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Note that the direct value retrieval in this implementation only supports + * String-type literals - nothing else! + * + * This implementation is mainly intended for optimizing database indexing + * performance. + */ public class DirectQuerySupportImpl implements DirectQuerySupport { private static final Logger LOGGER = LoggerFactory.getLogger(DirectQuerySupportImpl.class); @@ -559,6 +566,7 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { } + @SuppressWarnings("unchecked") private void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final ForPossibleRelatedValueProcedure procedure) { Object result = null; @@ -653,6 +661,7 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { } + @SuppressWarnings("unchecked") private void getValue4(final ReadGraphImpl graph, final ClusterImpl containerCluster, final int subject, final C context, final ForPossibleRelatedValueContextProcedure procedure) { Object result = null; @@ -891,7 +900,8 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { try { byte[] bytes = cluster.getValue(subject, session.clusterTranslator); - T value = (T)utf(bytes); + @SuppressWarnings("unchecked") + T value = (T)utf(bytes, 0); procedure.execute(graph, context, value); } catch (DatabaseException e) { procedure.execute(graph, context, null); @@ -905,7 +915,8 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { try { byte[] bytes = cluster.getValue(subject, session.clusterTranslator); - T value = (T)utf(bytes); + @SuppressWarnings("unchecked") + T value = (T)utf(bytes, 0); procedure.execute(graph, value); } catch (DatabaseException e) { procedure.execute(graph, null); @@ -922,7 +933,8 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { if(bytes == null) { procedure.execute(graph, context, null); } else { - T value = (T)utf(bytes); + @SuppressWarnings("unchecked") + T value = (T)utf(bytes, 0); procedure.execute(graph, context, value); } } catch (DatabaseException e) { @@ -934,38 +946,42 @@ public class DirectQuerySupportImpl implements DirectQuerySupport { } private void getDirectValue4(final ReadGraphImpl graph, final ClusterSmall cluster, final int subject, final ForPossibleRelatedValueProcedure procedure) { + try { + // Note: this code avoids creating an intermediate byte[] + // to store the encoded string bytes and reads the UTF string + // from the value table byte[] directly into String instead. - ResourceTableSmall rt = cluster.resourceTable; - ValueTableSmall vt = cluster.valueTable; - - byte[] bs = vt.table; - long[] ls = rt.table; + ResourceTableSmall rt = cluster.resourceTable; + ValueTableSmall vt = cluster.valueTable; - int index = ((subject&0xFFFF) << 1) - 1 + rt.offset; + byte[] bs = vt.table; + long[] ls = rt.table; - int valueIndex = (int)(ls[index] >>> 24) & 0x3FFFFF + vt.offset; + int index = ((subject&0xFFF) << 1) - 1 + rt.offset; + int valueIndex = ((int)(ls[index] >>> 24) & 0x3FFFFF) + vt.offset; - int size = (int)bs[valueIndex++]-1; - char[] chars = new char[size]; - valueIndex++; - for(int i=0;i= 0x80) { if(length >= 0xc0) { -- 2.47.1