hydrus/hydrus/client/db/ClientDBFilesMetadataBasic.py

177 lines
5.9 KiB
Python
Raw Normal View History

2021-02-17 18:22:44 +00:00
import os
import sqlite3
import typing
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusDB
from hydrus.core import HydrusDBModule
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusSerialisable
from hydrus.core import HydrusTags
from hydrus.client.db import ClientDBServices
from hydrus.client.metadata import ClientTags
class ClientDBFilesMetadataBasic( HydrusDBModule.HydrusDBModule ):
def __init__( self, cursor: sqlite3.Cursor ):
HydrusDBModule.HydrusDBModule.__init__( self, 'client files metadata', cursor )
self.inbox_hash_ids = set()
self._InitCaches()
def _GetInitialIndexGenerationTuples( self ):
index_generation_tuples = []
index_generation_tuples.append( ( 'files_info', [ 'size' ], False ) )
index_generation_tuples.append( ( 'files_info', [ 'mime' ], False ) )
index_generation_tuples.append( ( 'files_info', [ 'width' ], False ) )
index_generation_tuples.append( ( 'files_info', [ 'height' ], False ) )
index_generation_tuples.append( ( 'files_info', [ 'duration' ], False ) )
index_generation_tuples.append( ( 'files_info', [ 'num_frames' ], False ) )
return index_generation_tuples
def _InitCaches( self ):
if self._c.execute( 'SELECT 1 FROM sqlite_master WHERE name = ?;', ( 'file_inbox', ) ).fetchone() is not None:
self.inbox_hash_ids = self._STS( self._c.execute( 'SELECT hash_id FROM file_inbox;' ) )
def AddFilesInfo( self, rows, overwrite = False ):
if overwrite:
insert_phrase = 'REPLACE INTO'
else:
insert_phrase = 'INSERT OR IGNORE INTO'
# hash_id, size, mime, width, height, duration, num_frames, has_audio, num_words
self._c.executemany( insert_phrase + ' files_info ( hash_id, size, mime, width, height, duration, num_frames, has_audio, num_words ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? );', rows )
def ArchiveFiles( self, hash_ids: typing.Collection[ int ] ) -> typing.Set[ int ]:
if not isinstance( hash_ids, set ):
hash_ids = set( hash_ids )
archiveable_hash_ids = hash_ids.intersection( self.inbox_hash_ids )
if len( archiveable_hash_ids ) > 0:
self._c.executemany( 'DELETE FROM file_inbox WHERE hash_id = ?;', ( ( hash_id, ) for hash_id in archiveable_hash_ids ) )
self.inbox_hash_ids.difference_update( archiveable_hash_ids )
return archiveable_hash_ids
def CreateInitialTables( self ):
self._c.execute( 'CREATE TABLE file_inbox ( hash_id INTEGER PRIMARY KEY );' )
self._c.execute( 'CREATE TABLE files_info ( hash_id INTEGER PRIMARY KEY, size INTEGER, mime INTEGER, width INTEGER, height INTEGER, duration INTEGER, num_frames INTEGER, has_audio INTEGER_BOOLEAN, num_words INTEGER );' )
def GetExpectedTableNames( self ) -> typing.Collection[ str ]:
expected_table_names = [
'file_inbox',
'files_info'
]
return expected_table_names
def GetMime( self, hash_id: int ) -> int:
result = self._c.execute( 'SELECT mime FROM files_info WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
if result is None:
raise HydrusExceptions.DataMissing( 'Did not have mime information for that file!' )
( mime, ) = result
return mime
def GetNumViewable( self, hash_ids: typing.Collection[ int ] ) -> int:
if len( hash_ids ) == 1:
( hash_id, ) = hash_ids
result = self._STL( self._c.execute( 'SELECT mime FROM files_info WHERE hash_id = ?;', ( hash_id, ) ) )
else:
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_hash_ids_table_name:
result = self._STL( self._c.execute( 'SELECT mime FROM {} CROSS JOIN files_info USING ( hash_id );'.format( temp_hash_ids_table_name ) ) )
return sum( ( 1 for mime in result if mime in HC.SEARCHABLE_MIMES ) )
def GetTotalSize( self, hash_ids: typing.Collection[ int ] ) -> int:
if len( hash_ids ) == 1:
( hash_id, ) = hash_ids
result = self._c.execute( 'SELECT size FROM files_info WHERE hash_id = ?;', ( hash_id, ) ).fetchone()
else:
with HydrusDB.TemporaryIntegerTable( self._c, hash_ids, 'hash_id' ) as temp_hash_ids_table_name:
result = self._c.execute( 'SELECT SUM( size ) FROM {} CROSS JOIN files_info USING ( hash_id );'.format( temp_hash_ids_table_name ) ).fetchone()
if result is None:
return 0
( total_size, ) = result
return total_size
def InboxFiles( self, hash_ids: typing.Collection[ int ] ) -> typing.Set[ int ]:
if not isinstance( hash_ids, set ):
hash_ids = set( hash_ids )
inboxable_hash_ids = hash_ids.difference( self.inbox_hash_ids )
if len( inboxable_hash_ids ) > 0:
self._c.executemany( 'INSERT OR IGNORE INTO file_inbox VALUES ( ? );', ( ( hash_id, ) for hash_id in inboxable_hash_ids ) )
self.inbox_hash_ids.update( inboxable_hash_ids )
return inboxable_hash_ids