def addTrove(self, trove, pin = False, oldTroveSpec = None):
        cu = self.db.cursor()

        troveName = trove.getName()
        troveVersion = trove.getVersion()
        troveVersionId = self.getVersionId(troveVersion, {})
        self.addVersionCache[troveVersion] = troveVersionId

        if oldTroveSpec is not None:
            oldTroveId = self._findTroveInstanceId(cu, *oldTroveSpec)
        else:
            oldTroveId = None

        troveFlavor = trove.getFlavor()
        if not troveFlavor.isEmpty():
            self.flavorsNeeded[troveFlavor] = True

        for (name, version, flavor) in trove.iterTroveList(strongRefs=True,
                                                           weakRefs=True):
            if not flavor.isEmpty():
                self.flavorsNeeded[flavor] = True

        if self.flavorsNeeded:
            # create all of the flavor id's we'll need
            cu.execute("""
            CREATE TEMPORARY TABLE flavorsNeeded(
                empty INTEGER,
                flavor %(STRING)s
            )""" % self.db.keywords)
            for flavor in self.flavorsNeeded.keys():
                cu.execute("INSERT INTO flavorsNeeded VALUES(?, ?)",
                           None, flavor.freeze())
            cu.execute("""
            INSERT INTO Flavors (flavorId, flavor)
            SELECT flavorsNeeded.empty, flavorsNeeded.flavor
            FROM flavorsNeeded LEFT OUTER JOIN Flavors USING(flavor)
            WHERE Flavors.flavorId is NULL
            """)
            cu.execute("DROP TABLE flavorsNeeded")
            self.flavorsNeeded = {}

        # get all of the flavor id's we might need; this could be somewhat
        # more efficient for an update, but it's not clear making it
        # more efficient is actually a speedup (as we'd have to figure out
        # which flavorId's we need). it could be that all of this code
        # would get faster if we just added the files to a temporary table
        # first and insert'd into the final table???
        flavors = {}
        if not troveFlavor.isEmpty():
            flavors[troveFlavor] = True
        for (name, version, flavor) in trove.iterTroveList(strongRefs=True,
                                                           weakRefs=True):
            if not flavor.isEmpty():
                flavors[flavor] = True

        flavorMap = self.flavors.getItemDict(flavors.iterkeys())
        del flavors

        if troveFlavor.isEmpty():
            troveFlavorId = 0
        else:
            troveFlavorId = flavorMap[troveFlavor.freeze()]

        # the instance may already exist (it could be referenced by a package
        # which has already been added, or it may be in the database as
        # not present)
        troveInstanceId = self.instances.get((troveName, troveVersionId,
                                    troveFlavorId), None, justPresent = False)
        if troveInstanceId:
            self.instances.setPresent(troveInstanceId, 1, pinned=pin)
        else:
            assert(min(troveVersion.timeStamps()) > 0)
            troveInstanceId = self.instances.addId(troveName, troveVersionId,
                                       troveFlavorId, troveVersion.timeStamps(),
                                       pinned = pin)

        assert(cu.execute("SELECT COUNT(*) FROM TroveTroves WHERE "
                          "instanceId=?", troveInstanceId).next()[0] == 0)

        cu.execute("""
        CREATE TEMPORARY TABLE IncludedTroves(
            troveName   %(STRING)s,
            versionId   INTEGER,
            flavorId    INTEGER,
            timeStamps  %(STRING)s,
            flags       INTEGER
        ) """ % self.db.keywords)
        def _iter(trove):
            for (name, version, flavor), byDefault, isStrong \
                                                in trove.iterTroveListInfo():
                versionId = self.getVersionId(version, self.addVersionCache)
                if flavor.isEmpty():
                    flavorId = 0
                else:
                    flavorId = flavorMap[flavor.freeze()]

                flags = 0
                if not isStrong:
                    flags |= schema.TROVE_TROVES_WEAKREF
                if byDefault:
                    flags |= schema.TROVE_TROVES_BYDEFAULT;
                yield (name, versionId, flavorId,
                       ":".join([ "%.3f" % x for x in version.timeStamps()]),
                       flags)

        cu.executemany("INSERT INTO IncludedTroves VALUES(?, ?, ?, ?, ?)",
                       _iter(trove))

        # make sure every trove we include has an instanceid
        cu.execute("""
            INSERT INTO Instances (troveName, versionId, flavorId,
                                   timeStamps, isPresent, pinned)
                                    SELECT IncludedTroves.troveName,
                                           IncludedTroves.versionId,
                                           IncludedTroves.flavorId,
                                           IncludedTroves.timeStamps, 0, 0
                FROM IncludedTroves LEFT OUTER JOIN Instances ON
                    IncludedTroves.troveName == Instances.troveName AND
                    IncludedTroves.versionId == Instances.versionId AND
                    IncludedTroves.flavorId == Instances.flavorId
                WHERE
                    instanceId is NULL
            """)

        # now include the troves in this one
        cu.execute("""
            INSERT INTO TroveTroves(instanceId, includedId, flags, inPristine)
                SELECT ?, instanceId, flags, ?
                FROM IncludedTroves JOIN Instances ON
                    IncludedTroves.troveName == Instances.troveName AND
                    IncludedTroves.versionId == Instances.versionId AND
                    IncludedTroves.flavorId == Instances.flavorId
            """, troveInstanceId, True)

        cu.execute("DROP TABLE IncludedTroves")

        trove.troveInfo.installTime.set(time.time())
        self.depTables.add(cu, trove, troveInstanceId)
        self.troveInfoTable.addInfo(cu, trove, troveInstanceId)

        # these are collections that _could_ include trove (they have
        # an empty slot where this trove might fit)
        cu.execute('''SELECT TroveTroves.instanceId FROM Instances
                      JOIN TroveTroves
                        ON (Instances.instanceId = TroveTroves.includedId)
                      WHERE troveName = ? AND isPresent=0''', trove.getName())
        collections = cu.fetchall()

        cu.execute("select instanceId from trovetroves where includedid=?", troveInstanceId)
        collections += cu.fetchall()

        for x, in collections:
            self._sanitizeTroveCollection(cu, x, nameHint = trove.getName())

        self._sanitizeTroveCollection(cu, troveInstanceId)

        cu.execute("""CREATE TEMPORARY TABLE NewFiles (
                        pathId BLOB,
                        versionId INTEGER,
                        path %(PATHTYPE)s,
                        fileId BLOB,
                        stream BLOB,
                        isPresent INTEGER)""" % self.db.keywords)

        cu.execute("""CREATE TEMPORARY TABLE NewFileTags (
                        pathId BLOB,
                        tag %(STRING)s)""" % self.db.keywords)

        stmt = cu.compile("""
                INSERT INTO NewFiles (pathId, versionId, path, fileId,
                                      stream, isPresent)
                        VALUES (?, ?, ?, ?, ?, ?)""")

        return (cu, troveInstanceId, stmt, oldTroveId)