Index: /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py	(revision 61461)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testresults.py	(revision 61462)
@@ -251,4 +251,6 @@
     ksParam_iUnit               = 'TestResultValue_iUnit';
 
+    kasAllowNullAttributes      = [ 'idTestSet', ];
+
     def __init__(self):
         ModelDataBase.__init__(self)
@@ -313,9 +315,14 @@
     ksIdAttr    = 'idTestResultMsg';
 
-    ksParam_idTestResultMsg    = 'TestResultValue_idTestResultMsg';
-    ksParam_idTestResult       = 'TestResultValue_idTestResult';
-    ksParam_tsCreated          = 'TestResultValue_tsCreated';
-    ksParam_idStrMsg           = 'TestResultValue_idStrMsg';
-    ksParam_enmLevel           = 'TestResultValue_enmLevel';
+    ksParam_idTestResultMsg     = 'TestResultValue_idTestResultMsg';
+    ksParam_idTestResult        = 'TestResultValue_idTestResult';
+    ksParam_idTestSet           = 'TestResultValue_idTestSet';
+    ksParam_tsCreated           = 'TestResultValue_tsCreated';
+    ksParam_idStrMsg            = 'TestResultValue_idStrMsg';
+    ksParam_enmLevel            = 'TestResultValue_enmLevel';
+
+    kasAllowNullAttributes      = [ 'idTestSet', ];
+
+    kcDbColumns                 = 6
 
     def __init__(self):
@@ -323,4 +330,5 @@
         self.idTestResultMsg    = None;
         self.idTestResult       = None;
+        self.idTestSet          = None;
         self.tsCreated          = None;
         self.idStrMsg           = None;
@@ -337,7 +345,8 @@
         self.idTestResultMsg    = aoRow[0];
         self.idTestResult       = aoRow[1];
-        self.tsCreated          = aoRow[2];
-        self.idStrMsg           = aoRow[3];
-        self.enmLevel           = aoRow[4];
+        self.idTestSet          = aoRow[2];
+        self.tsCreated          = aoRow[3];
+        self.idStrMsg           = aoRow[4];
+        self.enmLevel           = aoRow[5];
         return self;
 
@@ -361,6 +370,7 @@
         """
         TestResultMsgData.initFromDbRow(self, aoRow);
-        self.sMsg = aoRow[5];
+        self.sMsg = aoRow[self.kcDbColumns];
         return self;
+
 
 class TestResultFileData(ModelDataBase):
@@ -402,8 +412,13 @@
     ## @}
 
+    kasAllowNullAttributes      = [ 'idTestSet', ];
+
+    kcDbColumns                 =  8
+
     def __init__(self):
         ModelDataBase.__init__(self)
         self.idTestResultFile   = None;
         self.idTestResult       = None;
+        self.idTestSet          = None;
         self.tsCreated          = None;
         self.idStrFile          = None;
@@ -422,9 +437,10 @@
         self.idTestResultFile   = aoRow[0];
         self.idTestResult       = aoRow[1];
-        self.tsCreated          = aoRow[2];
-        self.idStrFile          = aoRow[3];
-        self.idStrDescription   = aoRow[4];
-        self.idStrKind          = aoRow[5];
-        self.idStrMime          = aoRow[6];
+        self.idTestSet          = aoRow[2];
+        self.tsCreated          = aoRow[3];
+        self.idStrFile          = aoRow[4];
+        self.idStrDescription   = aoRow[5];
+        self.idStrKind          = aoRow[6];
+        self.idStrMime          = aoRow[7];
         return self;
 
@@ -454,8 +470,8 @@
         """
         TestResultFileData.initFromDbRow(self, aoRow);
-        self.sFile          = aoRow[7];
-        self.sDescription   = aoRow[8];
-        self.sKind          = aoRow[9];
-        self.sMime          = aoRow[10];
+        self.sFile          = aoRow[self.kcDbColumns];
+        self.sDescription   = aoRow[self.kcDbColumns + 1];
+        self.sKind          = aoRow[self.kcDbColumns + 2];
+        self.sMime          = aoRow[self.kcDbColumns + 3];
         return self;
 
@@ -1030,5 +1046,4 @@
                           'SELECT TestResultFiles.tsCreated\n'
                           'FROM   TestResultFiles\n'
-                          '  JOIN TestResults ON TestResultFiles.idTestResult = TestResults.idTestResult\n'
                           'WHERE  idTestSet = %s\n'
                           ') UNION (\n'
@@ -1039,5 +1054,4 @@
                           'SELECT TestResultMsgs.tsCreated\n'
                           'FROM   TestResultMsgs\n'
-                          '  JOIN TestResults ON TestResultMsgs.idTestResult = TestResults.idTestResult\n'
                           'WHERE  idTestSet = %s\n'
                           ') ORDER by 1'
@@ -1386,5 +1400,5 @@
         # First add a message.
         #
-        self._newFailureDetails(aoStack[0].idTestResult, sError, None);
+        self._newFailureDetails(aoStack[0].idTestResult, idTestSet, sError, None);
 
         #
@@ -1578,5 +1592,5 @@
         return True;
 
-    def _newFailureDetails(self, idTestResult, sText, dCounts, tsCreated = None, fCommit = False):
+    def _newFailureDetails(self, idTestResult, idTestSet, sText, dCounts, tsCreated = None, fCommit = False):
         """
         Creates a record detailing cause of failure.
@@ -1609,16 +1623,18 @@
             self._oDb.execute('INSERT INTO TestResultMsgs (\n'
                               '         idTestResult,\n'
+                              '         idTestSet,\n'
                               '         idStrMsg,\n'
                               '         enmLevel)\n'
-                              'VALUES ( %s, %s, %s)\n'
-                              , ( idTestResult, idStrMsg, 'failure',) );
+                              'VALUES ( %s, %s, %s, %s)\n'
+                              , ( idTestResult, idTestSet, idStrMsg, 'failure',) );
         else:
             self._oDb.execute('INSERT INTO TestResultMsgs (\n'
                               '         idTestResult,\n'
+                              '         idTestSet,\n'
                               '         tsCreated,\n'
                               '         idStrMsg,\n'
                               '         enmLevel)\n'
-                              'VALUES ( %s, TIMESTAMP WITH TIME ZONE %s, %s, %s)\n'
-                              , ( idTestResult, tsCreated, idStrMsg, 'failure',) );
+                              'VALUES ( %s, %s, TIMESTAMP WITH TIME ZONE %s, %s, %s)\n'
+                              , ( idTestResult, idTestSet, tsCreated, idStrMsg, 'failure',) );
 
         self._oDb.maybeCommit(fCommit);
@@ -1686,10 +1702,10 @@
         return None;
 
-    def _doPopHint(self, aoStack, cStackEntries, dCounts):
+    def _doPopHint(self, aoStack, cStackEntries, dCounts, idTestSet):
         """ Executes a PopHint. """
         assert cStackEntries >= 0;
         while len(aoStack) > cStackEntries:
             if aoStack[0].enmStatus == TestResultData.ksTestStatus_Running:
-                self._newFailureDetails(aoStack[0].idTestResult, 'XML error: Missing </Test>', dCounts);
+                self._newFailureDetails(aoStack[0].idTestResult, idTestSet, 'XML error: Missing </Test>', dCounts);
                 self._completeTestResults(aoStack[0], tsDone = None, cErrors = 1,
                                           enmStatus = TestResultData.ksTestStatus_Failure, fCommit = True);
@@ -1858,6 +1874,7 @@
 
         elif sName == 'FailureDetails':
-            self._newFailureDetails(idTestResult = aoStack[0].idTestResult, tsCreated = dAttribs['timestamp'],
-                                    sText = dAttribs['text'], dCounts = dCounts, fCommit = True);
+            self._newFailureDetails(idTestResult = aoStack[0].idTestResult, idTestSet = idTestSet,
+                                    tsCreated = dAttribs['timestamp'], sText = dAttribs['text'], dCounts = dCounts,
+                                    fCommit = True);
 
         elif sName == 'Passed':
@@ -1894,5 +1911,5 @@
             iDesiredTestDepth = int(dAttribs['testdepth']);
             cStackEntries, iTestDepth = aaiHints.pop(0);
-            self._doPopHint(aoStack, cStackEntries, dCounts); # Fake the necessary '<End/></Test>' tags.
+            self._doPopHint(aoStack, cStackEntries, dCounts, idTestSet); # Fake the necessary '<End/></Test>' tags.
             if iDesiredTestDepth != iTestDepth:
                 return 'PopHint tag has different testdepth: %d, on stack %d.' % (iDesiredTestDepth, iTestDepth);
@@ -1992,5 +2009,5 @@
             sError = 'Expected </PopHint> before the end of the XML section.'
         if len(aaiHints) > 0:
-            self._doPopHint(aoStack, aaiHints[-1][0], dCounts);
+            self._doPopHint(aoStack, aaiHints[-1][0], dCounts, idTestSet);
 
         #
Index: /trunk/src/VBox/ValidationKit/testmanager/core/testset.py
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/core/testset.py	(revision 61461)
+++ /trunk/src/VBox/ValidationKit/testmanager/core/testset.py	(revision 61462)
@@ -381,7 +381,7 @@
                                   'WHERE    idTestResult = %s\n'
                                   , (aoRow[0],));
-                self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idStrMsg, enmLevel)\n'
-                                  'VALUES ( %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
-                                  , (aoRow[0], idStr,));
+                self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idTestSet, idStrMsg, enmLevel)\n'
+                                  'VALUES ( %s, %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
+                                  , (aoRow[0], idTestSet, idStr,));
 
         #
@@ -476,7 +476,7 @@
 
             idStr = self.strTabString('The test was abandond by the testbox', fCommit = fCommit);
-            self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idStrMsg, enmLevel)\n'
-                              'VALUES ( %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
-                              , (oData.idTestResult, idStr,));
+            self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idTestSet, idStrMsg, enmLevel)\n'
+                              'VALUES ( %s, %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
+                              , (oData.idTestResult, idTestSet, idStr,));
 
         #
@@ -519,7 +519,7 @@
 
         idStr = self.strTabString('Gang gathering timed out', fCommit = fCommit);
-        self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idStrMsg, enmLevel)\n'
-                          'VALUES ( %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
-                          , (oData.idTestResult, idStr,));
+        self._oDb.execute('INSERT INTO TestResultMsgs (idTestResult, idTestSet, idStrMsg, enmLevel)\n'
+                          'VALUES ( %s, %s, %s, \'failure\'::TestResultMsgLevel_T)\n'
+                          , (oData.idTestResult, idTestSet, idStr,));
 
         self._oDb.execute('UPDATE   TestSets\n'
@@ -602,7 +602,9 @@
                 raise TMExceptionBase('Failed to find unique name for %s.' % (sOrgName,));
 
-        self._oDb.execute('INSERT INTO TestResultFiles(idTestResult, idStrFile, idStrDescription, idStrKind, idStrMime)\n'
-                          'VALUES (%s, %s, %s, %s, %s)\n'
+        self._oDb.execute('INSERT INTO TestResultFiles(idTestResult, idTestSet, idStrFile, idStrDescription,\n'
+                          '                            idStrKind, idStrMime)\n'
+                          'VALUES (%s, %s, %s, %s, %s, %s)\n'
                           , ( idTestResult,
+                              oTestSet.idTestSet,
                               self.strTabString(sName),
                               self.strTabString(sDesc),
Index: /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql
===================================================================
--- /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql	(revision 61461)
+++ /trunk/src/VBox/ValidationKit/testmanager/db/TestManagerDatabaseInit.pgsql	(revision 61462)
@@ -1293,5 +1293,5 @@
     -- This is NULL for the top test result.
     idTestResultParent  INTEGER     REFERENCES TestResults(idTestResult),
-    --- The testsest this result is a part of.
+    --- The test set this result is a part of.
     -- Note! This is a foreign key, but we have to add it after TestSets has
     --       been created, see further down.
@@ -1354,5 +1354,5 @@
     --- The test result it was reported within.
     idTestResult        INTEGER     REFERENCES TestResults(idTestResult)  NOT NULL,
-    --- The test result it was reported within.
+    --- The test set this value is a part of (for avoiding joining thru TestResults).
     -- Note! This is a foreign key, but we have to add it after TestSets has
     --       been created, see further down.
@@ -1400,4 +1400,8 @@
     --- The test result it was reported within.
     idTestResult        INTEGER     REFERENCES TestResults(idTestResult)  NOT NULL,
+    --- The test set this file is a part of (for avoiding joining thru TestResults).
+    -- Note! This is a foreign key, but we have to add it after TestSets has
+    --       been created, see further down.
+    idTestSet           INTEGER     NOT NULL,
     --- Creation time stamp.
     tsCreated           TIMESTAMP WITH TIME ZONE  DEFAULT current_timestamp  NOT NULL,
@@ -1425,4 +1429,5 @@
 
 CREATE INDEX TestResultFilesIdx ON TestResultFiles(idTestResult);
+CREATE INDEX TestResultFilesIdx2 ON TestResultFiles(idTestSet, tsCreated DESC);
 
 
@@ -1453,4 +1458,8 @@
     --- The test result it was reported within.
     idTestResult        INTEGER     REFERENCES TestResults(idTestResult)  NOT NULL,
+    --- The test set this file is a part of (for avoiding joining thru TestResults).
+    -- Note! This is a foreign key, but we have to add it after TestSets has
+    --       been created, see further down.
+    idTestSet           INTEGER     NOT NULL,
     --- Creation time stamp.
     tsCreated           TIMESTAMP WITH TIME ZONE  DEFAULT current_timestamp  NOT NULL,
@@ -1461,5 +1470,6 @@
 );
 
-CREATE INDEX TestResultMsgsIdx ON TestResultMsgs(idTestResult);
+CREATE INDEX TestResultMsgsIdx  ON TestResultMsgs(idTestResult);
+CREATE INDEX TestResultMsgsIdx2 ON TestResultMsgs(idTestSet, tsCreated DESC);
 
 
@@ -1571,4 +1581,6 @@
 ALTER TABLE TestResults      ADD FOREIGN KEY (idTestSet) REFERENCES TestSets(idTestSet) MATCH FULL;
 ALTER TABLE TestResultValues ADD FOREIGN KEY (idTestSet) REFERENCES TestSets(idTestSet) MATCH FULL;
+ALTER TABLE TestResultFiles  ADD FOREIGN KEY (idTestSet) REFERENCES TestSets(idTestSet) MATCH FULL;
+ALTER TABLE TestResultMsgs   ADD FOREIGN KEY (idTestSet) REFERENCES TestSets(idTestSet) MATCH FULL;
 ALTER TABLE TestResultFailures ADD CONSTRAINT idTestSetFk FOREIGN KEY (idTestSet) REFERENCES TestSets(idTestSet) MATCH FULL;
 
