Blob Blame History Raw
From e52b57b7a9f0303c0c710e60870d0ec265d32541 Mon Sep 17 00:00:00 2001
From: Milian Wolff <mail@milianw.de>
Date: Mon, 1 Dec 2014 14:11:19 +0100
Subject: [PATCH 19/30] Optimize queries: Do not retrieve known key used in the
 condition.

There is no point in doing a select like:

SELECT foo, bar FROM table WHERE foo = needle;

That can be rewritten to say

SELECT bar FROM table WHERE foo = needle;

This reduces the data traffic with the mysql server. Additionally, it
work-arounds some issues in Qt SQL, which lead to bad performance:
QSqlResult::value incurs multiple temporary allocations, and string
conversions, even to read a simple integer ID for example. Finally,
by reusing an externally provided QString name e.g., we can leverage
Qt's implicit sharing, instead of duplicating the string in a separate
QString instance, with the contents read from SQL server.

REVIEW: 121310
---
 server/src/storage/entities.xsl | 50 +++++++++++++++++++++++++++++------------
 1 file changed, 36 insertions(+), 14 deletions(-)

diff --git a/server/src/storage/entities.xsl b/server/src/storage/entities.xsl
index 9471293..c8fb1fd 100644
--- a/server/src/storage/entities.xsl
+++ b/server/src/storage/entities.xsl
@@ -104,6 +104,12 @@ Q_DECLARE_TYPEINFO( Akonadi::Server::<xsl:value-of select="@name"/>, Q_MOVABLE_T
 
 using namespace Akonadi::Server;
 
+static QStringList removeEntry(QStringList list, const QString&amp; entry)
+{
+  list.removeOne(entry);
+  return list;
+}
+
 <xsl:for-each select="database/table">
 <xsl:call-template name="table-source"/>
 </xsl:for-each>
@@ -179,7 +185,8 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
     return <xsl:value-of select="$className"/>();
 
   QueryBuilder qb( tableName(), QueryBuilder::Select );
-  qb.addColumns( columnNames() );
+  static const QStringList columns = removeEntry(columnNames(), <xsl:value-of select="$key"/>Column());
+  qb.addColumns( columns );
   qb.addValueCondition( <xsl:value-of select="$key"/>Column(), Query::Equals, <xsl:value-of select="$key"/> );
   if ( !qb.exec() ) {
     akDebug() &lt;&lt; "Error during selection of record with <xsl:value-of select="$key"/>"
@@ -191,21 +198,36 @@ set<xsl:value-of select="$methodName"/>( <xsl:call-template name="argument"/> )
     return <xsl:value-of select="$className"/>();
   }
 
+  <!-- this indirection is required to prevent off-by-one access now that we skip the key column -->
+  int valueIndex = 0;
+  <xsl:for-each select="column">
+    const <xsl:value-of select="@type"/> value<xsl:value-of select="position()"/> =
+    <xsl:choose>
+      <xsl:when test="@name=$key">
+        <xsl:value-of select="$key"/>;
+      </xsl:when>
+      <xsl:otherwise>
+        (qb.query().isNull(valueIndex)) ?
+        <xsl:value-of select="@type"/>() :
+        <xsl:choose>
+          <xsl:when test="starts-with(@type,'QString')">
+          Utils::variantToString( qb.query().value( valueIndex ) )
+          </xsl:when>
+          <xsl:when test="starts-with(@type, 'Tristate')">
+          static_cast&lt;Tristate&gt;(qb.query().value( valueIndex ).value&lt;int&gt;())
+          </xsl:when>
+          <xsl:otherwise>
+          qb.query().value( valueIndex ).value&lt;<xsl:value-of select="@type"/>&gt;()
+          </xsl:otherwise>
+        </xsl:choose>
+        ; ++valueIndex;
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:for-each>
+
   <xsl:value-of select="$className"/> rv(
   <xsl:for-each select="column">
-    (qb.query().isNull(<xsl:value-of select="position() - 1"/>)) ?
-      <xsl:value-of select="@type"/>() :
-      <xsl:choose>
-        <xsl:when test="starts-with(@type,'QString')">
-      Utils::variantToString( qb.query().value( <xsl:value-of select="position() - 1"/> ) )
-        </xsl:when>
-        <xsl:when test="starts-with(@type, 'Tristate')">
-      static_cast&lt;Tristate&gt;(qb.query().value( <xsl:value-of select="position() - 1"/> ).value&lt;int&gt;())
-        </xsl:when>
-        <xsl:otherwise>
-      qb.query().value( <xsl:value-of select="position() - 1"/> ).value&lt;<xsl:value-of select="@type"/>&gt;()
-        </xsl:otherwise>
-      </xsl:choose>
+    value<xsl:value-of select="position()"/>
     <xsl:if test="position() != last()">,</xsl:if>
   </xsl:for-each>
   );
-- 
2.1.0