2021-02-17 18:22:44 +00:00
import sqlite3
import typing
from hydrus . core import HydrusConstants as HC
2022-02-16 22:10:11 +00:00
from hydrus . core import HydrusData
2021-02-17 18:22:44 +00:00
from hydrus . core import HydrusExceptions
2022-03-09 22:18:23 +00:00
from hydrus . client import ClientTime
2021-09-15 04:23:53 +00:00
from hydrus . client . db import ClientDBModule
class ClientDBFilesMetadataBasic ( ClientDBModule . ClientDBModule ) :
2021-02-17 18:22:44 +00:00
def __init__ ( self , cursor : sqlite3 . Cursor ) :
2021-09-15 04:23:53 +00:00
ClientDBModule . ClientDBModule . __init__ ( self , ' client files metadata ' , cursor )
2021-02-17 18:22:44 +00:00
self . inbox_hash_ids = set ( )
self . _InitCaches ( )
2021-09-15 04:23:53 +00:00
def _GetInitialIndexGenerationDict ( self ) - > dict :
2021-02-17 18:22:44 +00:00
2021-09-15 04:23:53 +00:00
index_generation_dict = { }
2021-02-17 18:22:44 +00:00
2021-09-15 04:23:53 +00:00
index_generation_dict [ ' main.files_info ' ] = [
( [ ' size ' ] , False , 400 ) ,
( [ ' mime ' ] , False , 400 ) ,
( [ ' width ' ] , False , 400 ) ,
( [ ' height ' ] , False , 400 ) ,
( [ ' duration ' ] , False , 400 ) ,
( [ ' num_frames ' ] , False , 400 )
]
2021-02-17 18:22:44 +00:00
2022-02-16 22:10:11 +00:00
index_generation_dict [ ' main.archive_timestamps ' ] = [
( [ ' archived_timestamp ' ] , False , 474 )
]
2022-03-09 22:18:23 +00:00
index_generation_dict [ ' main.file_domain_modified_timestamps ' ] = [
( [ ' file_modified_timestamp ' ] , False , 476 )
]
2021-09-15 04:23:53 +00:00
return index_generation_dict
def _GetInitialTableGenerationDict ( self ) - > dict :
return {
2021-12-08 22:40:59 +00:00
' main.file_inbox ' : ( ' CREATE TABLE IF NOT EXISTS {} ( hash_id INTEGER PRIMARY KEY ); ' , 400 ) ,
' main.files_info ' : ( ' CREATE TABLE IF NOT EXISTS {} ( 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 ); ' , 400 ) ,
2022-02-16 22:10:11 +00:00
' main.has_icc_profile ' : ( ' CREATE TABLE IF NOT EXISTS {} ( hash_id INTEGER PRIMARY KEY ); ' , 465 ) ,
2022-03-09 22:18:23 +00:00
' main.archive_timestamps ' : ( ' CREATE TABLE IF NOT EXISTS {} ( hash_id INTEGER PRIMARY KEY, archived_timestamp INTEGER ); ' , 474 ) ,
' main.file_domain_modified_timestamps ' : ( ' CREATE TABLE IF NOT EXISTS {} ( hash_id INTEGER, domain_id INTEGER, file_modified_timestamp INTEGER, PRIMARY KEY ( hash_id, domain_id ) ); ' , 476 )
2021-09-15 04:23:53 +00:00
}
2021-02-17 18:22:44 +00:00
def _InitCaches ( self ) :
2021-08-11 21:14:12 +00:00
if self . _Execute ( ' SELECT 1 FROM sqlite_master WHERE name = ?; ' , ( ' file_inbox ' , ) ) . fetchone ( ) is not None :
2021-02-17 18:22:44 +00:00
2021-08-11 21:14:12 +00:00
self . inbox_hash_ids = self . _STS ( self . _Execute ( ' SELECT hash_id FROM file_inbox; ' ) )
2021-02-17 18:22:44 +00:00
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
2021-08-11 21:14:12 +00:00
self . _ExecuteMany ( insert_phrase + ' files_info ( hash_id, size, mime, width, height, duration, num_frames, has_audio, num_words ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ? ); ' , rows )
2021-02-17 18:22:44 +00:00
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 :
2021-08-11 21:14:12 +00:00
self . _ExecuteMany ( ' DELETE FROM file_inbox WHERE hash_id = ?; ' , ( ( hash_id , ) for hash_id in archiveable_hash_ids ) )
2021-02-17 18:22:44 +00:00
self . inbox_hash_ids . difference_update ( archiveable_hash_ids )
2022-02-16 22:10:11 +00:00
now = HydrusData . GetNow ( )
self . _ExecuteMany ( ' REPLACE INTO archive_timestamps ( hash_id, archived_timestamp ) VALUES ( ?, ? ); ' , ( ( hash_id , now ) for hash_id in archiveable_hash_ids ) )
2021-02-17 18:22:44 +00:00
return archiveable_hash_ids
2022-03-09 22:18:23 +00:00
def ClearDomainModifiedTimestamp ( self , hash_id : int , domain_id : int ) :
self . _Execute ( ' DELETE FROM file_domain_modified_timestamps WHERE hash_id = ? AND domain_id = ?; ' , ( hash_id , domain_id ) )
def GetDomainModifiedTimestamp ( self , hash_id : int , domain_id : int ) - > typing . Optional [ int ] :
result = self . _Execute ( ' SELECT file_modified_timestamp FROM file_domain_modified_timestamps WHERE hash_id = ? AND domain_id = ?; ' , ( hash_id , domain_id ) ) . fetchone ( )
if result is None :
return None
( timestamp , ) = result
return timestamp
2021-02-17 18:22:44 +00:00
def GetMime ( self , hash_id : int ) - > int :
2021-08-11 21:14:12 +00:00
result = self . _Execute ( ' SELECT mime FROM files_info WHERE hash_id = ?; ' , ( hash_id , ) ) . fetchone ( )
2021-02-17 18:22:44 +00:00
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
2021-08-11 21:14:12 +00:00
result = self . _STL ( self . _Execute ( ' SELECT mime FROM files_info WHERE hash_id = ?; ' , ( hash_id , ) ) )
2021-02-17 18:22:44 +00:00
else :
2021-08-11 21:14:12 +00:00
with self . _MakeTemporaryIntegerTable ( hash_ids , ' hash_id ' ) as temp_hash_ids_table_name :
2021-02-17 18:22:44 +00:00
2021-08-11 21:14:12 +00:00
result = self . _STL ( self . _Execute ( ' SELECT mime FROM {} CROSS JOIN files_info USING ( hash_id ); ' . format ( temp_hash_ids_table_name ) ) )
2021-02-17 18:22:44 +00:00
return sum ( ( 1 for mime in result if mime in HC . SEARCHABLE_MIMES ) )
2021-07-28 21:12:00 +00:00
def GetResolution ( self , hash_id : int ) :
2021-08-11 21:14:12 +00:00
result = self . _Execute ( ' SELECT width, height FROM files_info WHERE hash_id = ?; ' , ( hash_id , ) ) . fetchone ( )
2021-07-28 21:12:00 +00:00
if result is None :
return ( None , None )
return result
2021-03-10 23:10:11 +00:00
def GetTablesAndColumnsThatUseDefinitions ( self , content_type : int ) - > typing . List [ typing . Tuple [ str , str ] ] :
2022-02-02 22:14:01 +00:00
if content_type == HC . CONTENT_TYPE_HASH :
2021-03-10 23:10:11 +00:00
2021-12-08 22:40:59 +00:00
return [
( ' file_inbox ' , ' hash_id ' ) ,
( ' files_info ' , ' hash_id ' ) ,
2022-02-16 22:10:11 +00:00
( ' has_icc_profile ' , ' hash_id ' ) ,
( ' archive_timestamps ' , ' hash_id ' )
2021-12-08 22:40:59 +00:00
]
2021-03-10 23:10:11 +00:00
return [ ]
2021-02-17 18:22:44 +00:00
def GetTotalSize ( self , hash_ids : typing . Collection [ int ] ) - > int :
if len ( hash_ids ) == 1 :
( hash_id , ) = hash_ids
2021-08-11 21:14:12 +00:00
result = self . _Execute ( ' SELECT size FROM files_info WHERE hash_id = ?; ' , ( hash_id , ) ) . fetchone ( )
2021-02-17 18:22:44 +00:00
else :
2021-08-11 21:14:12 +00:00
with self . _MakeTemporaryIntegerTable ( hash_ids , ' hash_id ' ) as temp_hash_ids_table_name :
2021-02-17 18:22:44 +00:00
2021-08-11 21:14:12 +00:00
result = self . _Execute ( ' SELECT SUM( size ) FROM {} CROSS JOIN files_info USING ( hash_id ); ' . format ( temp_hash_ids_table_name ) ) . fetchone ( )
2021-02-17 18:22:44 +00:00
if result is None :
return 0
( total_size , ) = result
return total_size
2021-12-08 22:40:59 +00:00
def GetHasICCProfile ( self , hash_id : int ) :
result = self . _Execute ( ' SELECT hash_id FROM has_icc_profile WHERE hash_id = ?; ' , ( hash_id , ) ) . fetchone ( )
return result is not None
def GetHasICCProfileHashIds ( self , hash_ids : typing . Collection [ int ] ) - > typing . Set [ int ] :
with self . _MakeTemporaryIntegerTable ( hash_ids , ' hash_id ' ) as temp_hash_ids_table_name :
has_icc_profile_hash_ids = self . _STS ( self . _Execute ( ' SELECT hash_id FROM {} CROSS JOIN has_icc_profile USING ( hash_id ); ' . format ( temp_hash_ids_table_name ) ) )
return has_icc_profile_hash_ids
2021-02-17 18:22:44 +00:00
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 :
2021-08-11 21:14:12 +00:00
self . _ExecuteMany ( ' INSERT OR IGNORE INTO file_inbox VALUES ( ? ); ' , ( ( hash_id , ) for hash_id in inboxable_hash_ids ) )
2021-02-17 18:22:44 +00:00
self . inbox_hash_ids . update ( inboxable_hash_ids )
return inboxable_hash_ids
2022-03-09 22:18:23 +00:00
def SetDomainModifiedTimestamp ( self , hash_id : int , domain_id : int , timestamp : int ) :
self . _Execute ( ' REPLACE INTO file_domain_modified_timestamps ( hash_id, domain_id, file_modified_timestamp ) VALUES ( ?, ?, ? ); ' , ( hash_id , domain_id , timestamp ) )
2021-12-08 22:40:59 +00:00
def SetHasICCProfile ( self , hash_id : int , has_icc_profile : bool ) :
if has_icc_profile :
self . _Execute ( ' INSERT OR IGNORE INTO has_icc_profile ( hash_id ) VALUES ( ? ); ' , ( hash_id , ) )
else :
self . _Execute ( ' DELETE FROM has_icc_profile WHERE hash_id = ?; ' , ( hash_id , ) )
2022-03-09 22:18:23 +00:00
def UpdateDomainModifiedTimestamp ( self , hash_id : int , domain_id : int , timestamp : int ) :
should_update = True
existing_timestamp = self . GetDomainModifiedTimestamp ( hash_id , domain_id )
if existing_timestamp is not None :
should_update = ClientTime . ShouldUpdateDomainModifiedTime ( existing_timestamp , timestamp )
if should_update :
self . SetDomainModifiedTimestamp ( hash_id , domain_id , timestamp )