diff --git a/lib/Db/TimelineQueryTags.php b/lib/Db/TimelineQueryTags.php index 24cef447..45ad5edb 100644 --- a/lib/Db/TimelineQueryTags.php +++ b/lib/Db/TimelineQueryTags.php @@ -33,7 +33,7 @@ trait TimelineQueryTags $query->innerJoin('m', 'systemtag_object_mapping', 'stom', $query->expr()->andX( $query->expr()->eq('stom.objecttype', $query->createNamedParameter('files')), - $query->expr()->eq('stom.objectid', 'm.fileid'), + $query->expr()->eq('stom.objectid', 'm.objectid'), $query->expr()->eq('stom.systemtagid', $query->createNamedParameter($tagId)), )); } @@ -55,20 +55,10 @@ trait TimelineQueryTags )); // WHERE these items are memories indexed photos - $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid')); + $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid')); // WHERE these photos are in the user's requested folder recursively - // This is a hack to speed up the query instead of using joinFilecache - // The problem is objectid is VARCHAR(64) and fileid is BIGINT(20), so a - // join is extremely slow. Instead, we use a subquery to check existence. - // - // https://blog.sqlauthority.com/2010/06/05/sql-server-convert-in-to-exists-performance-talk/ - - $this->addSubfolderJoinParams($query, $folder, false); - $query->innerJoin('m', 'filecache', 'f', $query->expr()->andX( - $query->expr()->eq('f.fileid', 'm.fileid'), - $query->createFunction('EXISTS (SELECT 1 from *PREFIX*cte_folders WHERE *PREFIX*cte_folders.fileid = `f`.parent)') - )); + $query = $this->joinFilecache($query, $folder, true, false); // GROUP and ORDER by tag name $query->groupBy('st.name'); @@ -106,15 +96,10 @@ trait TimelineQueryTags ); // WHERE these items are memories indexed photos - $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.fileid', 'stom.objectid')); + $query->innerJoin('stom', 'memories', 'm', $query->expr()->eq('m.objectid', 'stom.objectid')); // WHERE these photos are in the user's requested folder recursively - // See the function above for an explanation of this hack - $this->addSubfolderJoinParams($query, $folder, false); - $query->innerJoin('m', 'filecache', 'f', $query->expr()->andX( - $query->expr()->eq('f.fileid', 'm.fileid'), - $query->createFunction('EXISTS (SELECT 1 from *PREFIX*cte_folders WHERE *PREFIX*cte_folders.fileid = `f`.parent)') - )); + $query = $this->joinFilecache($query, $folder, true, false); // MAX 4 $query->setMaxResults(4); diff --git a/lib/Db/TimelineWrite.php b/lib/Db/TimelineWrite.php index b0b35a52..20c11b07 100644 --- a/lib/Db/TimelineWrite.php +++ b/lib/Db/TimelineWrite.php @@ -99,6 +99,7 @@ class TimelineWrite if ($prevRow) { // Update existing row + // No need to set objectid again $query->update('memories') ->set('dayid', $query->createNamedParameter($dayId, IQueryBuilder::PARAM_INT)) ->set('datetaken', $query->createNamedParameter($dateTaken, IQueryBuilder::PARAM_STR)) @@ -115,6 +116,7 @@ class TimelineWrite $query->insert('memories') ->values([ 'fileid' => $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT), + 'objectid' => $query->createNamedParameter((string) $fileId, IQueryBuilder::PARAM_STR), 'dayid' => $query->createNamedParameter($dayId, IQueryBuilder::PARAM_INT), 'datetaken' => $query->createNamedParameter($dateTaken, IQueryBuilder::PARAM_STR), 'mtime' => $query->createNamedParameter($mtime, IQueryBuilder::PARAM_INT), diff --git a/lib/Migration/Version400503Date20221101033144.php b/lib/Migration/Version400503Date20221101033144.php new file mode 100644 index 00000000..dc20d4a5 --- /dev/null +++ b/lib/Migration/Version400503Date20221101033144.php @@ -0,0 +1,86 @@ + + * @author Your name + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace OCA\Memories\Migration; + +use Closure; +use OCP\DB\ISchemaWrapper; +use OCP\IDBConnection; +use OCP\Migration\IOutput; +use OCP\Migration\SimpleMigrationStep; + +/** + * Auto-generated migration step: Please modify to your needs! + */ +class Version400503Date20221101033144 extends SimpleMigrationStep +{ + /** @var IDBConnection */ + private $dbc; + + public function __construct(IDBConnection $dbc) + { + $this->dbc = $dbc; + } + + /** + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void + { + } + + /** + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper + { + /** @var ISchemaWrapper $schema */ + $schema = $schemaClosure(); + + $table = $schema->getTable('memories'); + + // This is a hack to speed up the tags queries. + // The problem is objectid in systemtags is VARCHAR(64) while fileid in + // filecache and memories is BIGINT(20), so a join is extremely slow, + // because the entire tags table must be scanned for the conversion. + + $table->addColumn('objectid', 'string', [ + 'notnull' => true, + 'length' => 64, + 'default' => '0', // set to real value in postSchemaChange + ]); + + $table->addIndex(['objectid'], 'memories_objectid_index'); + + return $schema; + } + + /** + * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` + */ + public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void + { + // Update oc_memories to set objectid equal to fileid for all rows + $this->dbc->executeQuery('UPDATE *PREFIX*memories SET objectid = CAST(fileid AS CHAR)'); + } +}