summaryrefslogtreecommitdiff
path: root/plugin.video.mediathekview/resources/lib/storemysql.py
diff options
context:
space:
mode:
Diffstat (limited to 'plugin.video.mediathekview/resources/lib/storemysql.py')
-rw-r--r--plugin.video.mediathekview/resources/lib/storemysql.py913
1 files changed, 913 insertions, 0 deletions
diff --git a/plugin.video.mediathekview/resources/lib/storemysql.py b/plugin.video.mediathekview/resources/lib/storemysql.py
new file mode 100644
index 0000000..e2419cc
--- /dev/null
+++ b/plugin.video.mediathekview/resources/lib/storemysql.py
@@ -0,0 +1,913 @@
+# -*- coding: utf-8 -*-
+# Copyright 2017 Leo Moll
+#
+
+# -- Imports ------------------------------------------------
+import time
+import mysql.connector
+
+import resources.lib.mvutils as mvutils
+
+from resources.lib.film import Film
+
+# -- Classes ------------------------------------------------
+class StoreMySQL( object ):
+ def __init__( self, logger, notifier, settings ):
+ self.conn = None
+ self.logger = logger
+ self.notifier = notifier
+ self.settings = settings
+ # useful query fragments
+ self.sql_query_films = "SELECT film.id,`title`,`show`,`channel`,`description`,TIME_TO_SEC(`duration`) AS `seconds`,`size`,`aired`,`url_sub`,`url_video`,`url_video_sd`,`url_video_hd` FROM `film` LEFT JOIN `show` ON show.id=film.showid LEFT JOIN `channel` ON channel.id=film.channelid"
+ self.sql_query_filmcnt = "SELECT COUNT(*) FROM `film` LEFT JOIN `show` ON show.id=film.showid LEFT JOIN `channel` ON channel.id=film.channelid"
+ self.sql_cond_recent = "( TIMESTAMPDIFF(HOUR,`aired`,CURRENT_TIMESTAMP()) < 24 )"
+ self.sql_cond_nofuture = " AND ( ( `aired` IS NULL ) OR ( TIMESTAMPDIFF(HOUR,`aired`,CURRENT_TIMESTAMP()) > 0 ) )" if settings.nofuture else ""
+ self.sql_cond_minlength = " AND ( ( `duration` IS NULL ) OR ( TIME_TO_SEC(`duration`) >= %d ) )" % settings.minlength if settings.minlength > 0 else ""
+
+ def Init( self, reset = False ):
+ self.logger.info( 'Using MySQL connector version {}', mysql.connector.__version__ )
+ try:
+ self.conn = mysql.connector.connect(
+ host = self.settings.host,
+ port = self.settings.port,
+ user = self.settings.user,
+ password = self.settings.password
+ )
+ self.conn.database = self.settings.database
+ except mysql.connector.Error as err:
+ if err.errno == mysql.connector.errorcode.ER_BAD_DB_ERROR:
+ self.logger.info( '=== DATABASE {} DOES NOT EXIST. TRYING TO CREATE IT ===', self.settings.database )
+ self._handle_database_initialization()
+ return
+ self.conn = None
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def Exit( self ):
+ if self.conn is not None:
+ self.conn.close()
+
+ def Search( self, search, filmui ):
+ self._Search_Condition( '( ( `title` LIKE "%%%s%%" ) OR ( `show` LIKE "%%%s%%" ) )' % ( search, search, ), filmui, True, True, self.settings.maxresults )
+
+ def SearchFull( self, search, filmui ):
+ self._Search_Condition( '( ( `title` LIKE "%%%s%%" ) OR ( `show` LIKE "%%%s%%" ) ) OR ( `description` LIKE "%%%s%%") )' % ( search, search, search ), filmui, True, True, self.settings.maxresults )
+
+ def GetRecents( self, channelid, filmui ):
+ sql_cond_channel = ' AND ( film.channelid=' + str( channelid ) + ' ) ' if channelid != '0' else ''
+ self._Search_Condition( self.sql_cond_recent + sql_cond_channel, filmui, True, False, 10000 )
+
+ def GetLiveStreams( self, filmui ):
+ self._Search_Condition( '( show.search="LIVESTREAM" )', filmui, False, False, 10000 )
+
+ def GetChannels( self, channelui ):
+ self._Channels_Condition( None, channelui )
+
+ def GetRecentChannels( self, channelui ):
+ self._Channels_Condition( self.sql_cond_recent, channelui )
+
+ def GetInitials( self, channelid, initialui ):
+ if self.conn is None:
+ return
+ try:
+ condition = 'WHERE ( `channelid`=' + str( channelid ) + ' ) ' if channelid != '0' else ''
+ self.logger.info( 'MySQL Query: {}',
+ 'SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` ' +
+ condition +
+ 'GROUP BY LEFT(search,1)'
+ )
+ cursor = self.conn.cursor()
+ cursor.execute(
+ 'SELECT LEFT(`search`,1) AS letter,COUNT(*) AS `count` FROM `show` ' +
+ condition +
+ 'GROUP BY LEFT(`search`,1)'
+ )
+ initialui.Begin( channelid )
+ for ( initialui.initial, initialui.count ) in cursor:
+ initialui.Add()
+ initialui.End()
+ cursor.close()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def GetShows( self, channelid, initial, showui ):
+ if self.conn is None:
+ return
+ try:
+ if channelid == '0' and self.settings.groupshows:
+ query = 'SELECT GROUP_CONCAT(show.id),GROUP_CONCAT(`channelid`),`show`,GROUP_CONCAT(`channel`) FROM `show` LEFT JOIN `channel` ON channel.id=show.channelid WHERE ( `show` LIKE "%s%%" ) GROUP BY `show`' % initial
+ elif channelid == '0':
+ query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM `show` LEFT JOIN channel ON channel.id=show.channelid WHERE ( `show` LIKE "%s%%" )' % initial
+ else:
+ query = 'SELECT show.id,show.channelid,show.show,channel.channel FROM `show` LEFT JOIN channel ON channel.id=show.channelid WHERE ( `channelid`=%s ) AND ( `show` LIKE "%s%%" )' % ( channelid, initial )
+ self.logger.info( 'MySQL Query: {}', query )
+ cursor = self.conn.cursor()
+ cursor.execute( query )
+ showui.Begin( channelid )
+ for ( showui.id, showui.channelid, showui.show, showui.channel ) in cursor:
+ showui.Add()
+ showui.End()
+ cursor.close()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def GetFilms( self, showid, filmui ):
+ if self.conn is None:
+ return
+ if showid.find( ',' ) == -1:
+ # only one channel id
+ condition = '( `showid`=%s )' % showid
+ showchannels = False
+ else:
+ # multiple channel ids
+ condition = '( `showid` IN ( %s ) )' % showid
+ showchannels = True
+ self._Search_Condition( condition, filmui, False, showchannels, 10000 )
+
+ def _Channels_Condition( self, condition, channelui):
+ if self.conn is None:
+ return
+ try:
+ if condition is None:
+ query = 'SELECT `id`,`channel`,0 AS `count` FROM `channel`'
+ else:
+ query = 'SELECT channel.id AS `id`,`channel`,COUNT(*) AS `count` FROM `film` LEFT JOIN `channel` ON channel.id=film.channelid WHERE ' + condition + ' GROUP BY channel.id'
+ self.logger.info( 'MySQL Query: {}', query )
+ cursor = self.conn.cursor()
+ cursor.execute( query )
+ channelui.Begin()
+ for ( channelui.id, channelui.channel, channelui.count ) in cursor:
+ channelui.Add()
+ channelui.End()
+ cursor.close()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def _Search_Condition( self, condition, filmui, showshows, showchannels, maxresults ):
+ if self.conn is None:
+ return
+ try:
+ self.logger.info( 'MySQL Query: {}',
+ self.sql_query_films +
+ ' WHERE ' +
+ condition +
+ self.sql_cond_nofuture +
+ self.sql_cond_minlength
+ )
+ cursor = self.conn.cursor()
+ cursor.execute(
+ self.sql_query_filmcnt +
+ ' WHERE ' +
+ condition +
+ self.sql_cond_nofuture +
+ self.sql_cond_minlength +
+ ' LIMIT {}'.format( maxresults + 1 ) if maxresults else ''
+ )
+ ( results, ) = cursor.fetchone()
+ if maxresults and results > maxresults:
+ self.notifier.ShowLimitResults( maxresults )
+ cursor.execute(
+ self.sql_query_films +
+ ' WHERE ' +
+ condition +
+ self.sql_cond_nofuture +
+ self.sql_cond_minlength +
+ ' LIMIT {}'.format( maxresults + 1 ) if maxresults else ''
+ )
+ filmui.Begin( showshows, showchannels )
+ for ( filmui.id, filmui.title, filmui.show, filmui.channel, filmui.description, filmui.seconds, filmui.size, filmui.aired, filmui.url_sub, filmui.url_video, filmui.url_video_sd, filmui.url_video_hd ) in cursor:
+ filmui.Add( totalItems = results )
+ filmui.End()
+ cursor.close()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def RetrieveFilmInfo( self, filmid ):
+ if self.conn is None:
+ return None
+ try:
+ condition = '( film.id={} )'.format( filmid )
+ self.logger.info( 'MySQL Query: {}',
+ self.sql_query_films +
+ ' WHERE ' +
+ condition
+ )
+ cursor = self.conn.cursor()
+ cursor.execute(
+ self.sql_query_films +
+ ' WHERE ' +
+ condition
+ )
+ film = Film()
+ for ( film.id, film.title, film.show, film.channel, film.description, film.seconds, film.size, film.aired, film.url_sub, film.url_video, film.url_video_sd, film.url_video_hd ) in cursor:
+ cursor.close()
+ return film
+ cursor.close()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return None
+
+ def GetStatus( self ):
+ status = {
+ 'modified': int( time.time() ),
+ 'status': '',
+ 'lastupdate': 0,
+ 'filmupdate': 0,
+ 'fullupdate': 0,
+ 'add_chn': 0,
+ 'add_shw': 0,
+ 'add_mov': 0,
+ 'del_chn': 0,
+ 'del_shw': 0,
+ 'del_mov': 0,
+ 'tot_chn': 0,
+ 'tot_shw': 0,
+ 'tot_mov': 0
+ }
+ if self.conn is None:
+ status['status'] = "UNINIT"
+ return status
+ try:
+ cursor = self.conn.cursor()
+ cursor.execute( 'SELECT * FROM `status` LIMIT 1' )
+ r = cursor.fetchall()
+ cursor.close()
+ self.conn.commit()
+ if len( r ) == 0:
+ status['status'] = "NONE"
+ return status
+ status['modified'] = r[0][0]
+ status['status'] = r[0][1]
+ status['lastupdate'] = r[0][2]
+ status['filmupdate'] = r[0][3]
+ status['fullupdate'] = r[0][4]
+ status['add_chn'] = r[0][5]
+ status['add_shw'] = r[0][6]
+ status['add_mov'] = r[0][7]
+ status['del_chn'] = r[0][8]
+ status['del_shw'] = r[0][9]
+ status['del_mov'] = r[0][10]
+ status['tot_chn'] = r[0][11]
+ status['tot_shw'] = r[0][12]
+ status['tot_mov'] = r[0][13]
+ return status
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ status['status'] = "UNINIT"
+ return status
+
+ def UpdateStatus( self, status = None, lastupdate = None, filmupdate = None, fullupdate = None, add_chn = None, add_shw = None, add_mov = None, del_chn = None, del_shw = None, del_mov = None, tot_chn = None, tot_shw = None, tot_mov = None ):
+ if self.conn is None:
+ return
+ new = self.GetStatus()
+ old = new['status']
+ if status is not None:
+ new['status'] = status
+ if lastupdate is not None:
+ new['lastupdate'] = lastupdate
+ if filmupdate is not None:
+ new['filmupdate'] = filmupdate
+ if fullupdate is not None:
+ new['fullupdate'] = fullupdate
+ if add_chn is not None:
+ new['add_chn'] = add_chn
+ if add_shw is not None:
+ new['add_shw'] = add_shw
+ if add_mov is not None:
+ new['add_mov'] = add_mov
+ if del_chn is not None:
+ new['del_chn'] = del_chn
+ if del_shw is not None:
+ new['del_shw'] = del_shw
+ if del_mov is not None:
+ new['del_mov'] = del_mov
+ if tot_chn is not None:
+ new['tot_chn'] = tot_chn
+ if tot_shw is not None:
+ new['tot_shw'] = tot_shw
+ if tot_mov is not None:
+ new['tot_mov'] = tot_mov
+ # TODO: we should only write, if we have changed something...
+ new['modified'] = int( time.time() )
+ try:
+ cursor = self.conn.cursor()
+ if old == "NONE":
+ # insert status
+ cursor.execute(
+ """
+ INSERT INTO `status` (
+ `modified`,
+ `status`,
+ `lastupdate`,
+ `filmupdate`,
+ `fullupdate`,
+ `add_chn`,
+ `add_shw`,
+ `add_mov`,
+ `del_chm`,
+ `del_shw`,
+ `del_mov`,
+ `tot_chn`,
+ `tot_shw`,
+ `tot_mov`
+ )
+ VALUES (
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s,
+ %s
+ )
+ """, (
+ new['modified'],
+ new['status'],
+ new['lastupdate'],
+ new['filmupdate'],
+ new['fullupdate'],
+ new['add_chn'],
+ new['add_shw'],
+ new['add_mov'],
+ new['del_chn'],
+ new['del_shw'],
+ new['del_mov'],
+ new['tot_chn'],
+ new['tot_shw'],
+ new['tot_mov'],
+ )
+ )
+ else:
+ # update status
+ cursor.execute(
+ """
+ UPDATE `status`
+ SET `modified` = %s,
+ `status` = %s,
+ `lastupdate` = %s,
+ `filmupdate` = %s,
+ `fullupdate` = %s,
+ `add_chn` = %s,
+ `add_shw` = %s,
+ `add_mov` = %s,
+ `del_chm` = %s,
+ `del_shw` = %s,
+ `del_mov` = %s,
+ `tot_chn` = %s,
+ `tot_shw` = %s,
+ `tot_mov` = %s
+ """, (
+ new['modified'],
+ new['status'],
+ new['lastupdate'],
+ new['filmupdate'],
+ new['fullupdate'],
+ new['add_chn'],
+ new['add_shw'],
+ new['add_mov'],
+ new['del_chn'],
+ new['del_shw'],
+ new['del_mov'],
+ new['tot_chn'],
+ new['tot_shw'],
+ new['tot_mov'],
+ )
+ )
+ cursor.close()
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+
+ def SupportsUpdate( self ):
+ return True
+
+ def ftInit( self ):
+ # prevent concurrent updating
+ cursor = self.conn.cursor()
+ cursor.execute(
+ """
+ UPDATE `status`
+ SET `modified` = %s,
+ `status` = 'UPDATING'
+ WHERE ( `status` != 'UPDATING' )
+ OR
+ ( `modified` < %s )
+ """, (
+ int( time.time() ),
+ int( time.time() ) - 86400
+ )
+ )
+ retval = cursor.rowcount > 0
+ self.conn.commit()
+ cursor.close()
+ self.ft_channel = None
+ self.ft_channelid = None
+ self.ft_show = None
+ self.ft_showid = None
+ return retval
+
+ def ftUpdateStart( self, full ):
+ param = ( 1, ) if full else ( 0, )
+ try:
+ cursor = self.conn.cursor()
+ cursor.callproc( 'ftUpdateStart', param )
+ for result in cursor.stored_results():
+ for ( cnt_chn, cnt_shw, cnt_mov ) in result:
+ cursor.close()
+ self.conn.commit()
+ return ( cnt_chn, cnt_shw, cnt_mov )
+ # should never happen
+ cursor.close()
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return ( 0, 0, 0, )
+
+ def ftUpdateEnd( self, delete ):
+ param = ( 1, ) if delete else ( 0, )
+ try:
+ cursor = self.conn.cursor()
+ cursor.callproc( 'ftUpdateEnd', param )
+ for result in cursor.stored_results():
+ for ( del_chn, del_shw, del_mov, cnt_chn, cnt_shw, cnt_mov ) in result:
+ cursor.close()
+ self.conn.commit()
+ return ( del_chn, del_shw, del_mov, cnt_chn, cnt_shw, cnt_mov )
+ # should never happen
+ cursor.close()
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return ( 0, 0, 0, 0, 0, 0, )
+
+ def ftInsertFilm( self, film, commit ):
+ newchn = False
+ inschn = 0
+ insshw = 0
+ insmov = 0
+
+ # handle channel
+ if self.ft_channel != film['channel']:
+ # process changed channel
+ newchn = True
+ self.ft_channel = film['channel']
+ ( self.ft_channelid, inschn ) = self._insert_channel( self.ft_channel )
+ if self.ft_channelid == 0:
+ self.logger.info( 'Undefined error adding channel "{}"', self.ft_channel )
+ return ( 0, 0, 0, 0, )
+
+ if newchn or self.ft_show != film['show']:
+ # process changed show
+ self.ft_show = film['show']
+ ( self.ft_showid, insshw ) = self._insert_show( self.ft_channelid, self.ft_show, mvutils.make_search_string( self.ft_show ) )
+ if self.ft_showid == 0:
+ self.logger.info( 'Undefined error adding show "{}"', self.ft_show )
+ return ( 0, 0, 0, 0, )
+
+ try:
+ cursor = self.conn.cursor()
+ cursor.callproc( 'ftInsertFilm', (
+ self.ft_channelid,
+ self.ft_showid,
+ film["title"],
+ mvutils.make_search_string( film['title'] ),
+ film["aired"],
+ film["duration"],
+ film["size"],
+ film["description"],
+ film["website"],
+ film["url_sub"],
+ film["url_video"],
+ film["url_video_sd"],
+ film["url_video_hd"],
+ film["airedepoch"],
+ ) )
+ for result in cursor.stored_results():
+ for ( filmid, insmov ) in result:
+ cursor.close()
+ if commit:
+ self.conn.commit()
+ return ( filmid, inschn, insshw, insmov )
+ # should never happen
+ cursor.close()
+ if commit:
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return ( 0, 0, 0, 0, )
+
+ def _insert_channel( self, channel ):
+ try:
+ cursor = self.conn.cursor()
+ cursor.callproc( 'ftInsertChannel', ( channel, ) )
+ for result in cursor.stored_results():
+ for ( id, added ) in result:
+ cursor.close()
+ self.conn.commit()
+ return ( id, added )
+ # should never happen
+ cursor.close()
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return ( 0, 0, )
+
+ def _insert_show( self, channelid, show, search ):
+ try:
+ cursor = self.conn.cursor()
+ cursor.callproc( 'ftInsertShow', ( channelid, show, search, ) )
+ for result in cursor.stored_results():
+ for ( idd, added ) in result:
+ cursor.close()
+ self.conn.commit()
+ return ( idd, added )
+ # should never happen
+ cursor.close()
+ self.conn.commit()
+ except mysql.connector.Error as err:
+ self.logger.error( 'Database error: {}', err )
+ self.notifier.ShowDatabaseError( err )
+ return ( 0, 0, )
+
+ def _handle_database_initialization( self ):
+ cursor = None
+ dbcreated = False
+ try:
+ cursor = self.conn.cursor()
+ cursor.execute( 'CREATE DATABASE `{}` DEFAULT CHARACTER SET utf8'.format( self.settings.database ) )
+ dbcreated = True
+ self.conn.database = self.settings.database
+ cursor.execute( 'SET FOREIGN_KEY_CHECKS=0' )
+ self.conn.commit()
+ cursor.execute(
+ """
+CREATE TABLE `channel` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `dtCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `touched` smallint(1) NOT NULL DEFAULT '1',
+ `channel` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `channel` (`channel`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ """
+ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE TABLE `film` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `dtCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `touched` smallint(1) NOT NULL DEFAULT '1',
+ `channelid` int(11) NOT NULL,
+ `showid` int(11) NOT NULL,
+ `title` varchar(255) NOT NULL,
+ `search` varchar(255) NOT NULL,
+ `aired` timestamp NULL DEFAULT NULL,
+ `duration` time DEFAULT NULL,
+ `size` int(11) DEFAULT NULL,
+ `description` longtext,
+ `website` varchar(384) DEFAULT NULL,
+ `url_sub` varchar(384) DEFAULT NULL,
+ `url_video` varchar(384) DEFAULT NULL,
+ `url_video_sd` varchar(384) DEFAULT NULL,
+ `url_video_hd` varchar(384) DEFAULT NULL,
+ `airedepoch` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `index_1` (`showid`,`title`),
+ KEY `index_2` (`channelid`,`title`),
+ KEY `dupecheck` (`channelid`,`showid`,`url_video`),
+ CONSTRAINT `FK_FilmChannel` FOREIGN KEY (`channelid`) REFERENCES `channel` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION,
+ CONSTRAINT `FK_FilmShow` FOREIGN KEY (`showid`) REFERENCES `show` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE TABLE `show` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `dtCreated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `touched` smallint(1) NOT NULL DEFAULT '1',
+ `channelid` int(11) NOT NULL,
+ `show` varchar(255) NOT NULL,
+ `search` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`),
+ KEY `show` (`show`),
+ KEY `search` (`search`),
+ KEY `combined_1` (`channelid`,`search`),
+ KEY `combined_2` (`channelid`,`show`),
+ CONSTRAINT `FK_ShowChannel` FOREIGN KEY (`channelid`) REFERENCES `channel` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE TABLE `status` (
+ `modified` int(11) NOT NULL,
+ `status` varchar(255) NOT NULL,
+ `lastupdate` int(11) NOT NULL,
+ `filmupdate` int(11) NOT NULL,
+ `fullupdate` int(1) NOT NULL,
+ `add_chn` int(11) NOT NULL,
+ `add_shw` int(11) NOT NULL,
+ `add_mov` int(11) NOT NULL,
+ `del_chm` int(11) NOT NULL,
+ `del_shw` int(11) NOT NULL,
+ `del_mov` int(11) NOT NULL,
+ `tot_chn` int(11) NOT NULL,
+ `tot_shw` int(11) NOT NULL,
+ `tot_mov` int(11) NOT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+ """ )
+ self.conn.commit()
+
+ cursor.execute( 'INSERT INTO `status` VALUES (0,"IDLE",0,0,0,0,0,0,0,0,0,0,0,0);' )
+ self.conn.commit()
+
+ cursor.execute( 'SET FOREIGN_KEY_CHECKS=1' )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE PROCEDURE `ftInsertChannel`(
+ _channel VARCHAR(255)
+)
+BEGIN
+ DECLARE channelid_ INT(11);
+ DECLARE touched_ INT(1);
+ DECLARE added_ INT(1) DEFAULT 0;
+
+ SELECT `id`,
+ `touched`
+ INTO channelid_,
+ touched_
+ FROM `channel`
+ WHERE ( `channel`.`channel` = _channel );
+
+ IF ( channelid_ IS NULL ) THEN
+ INSERT INTO `channel` (
+ `channel`
+ )
+ VALUES (
+ _channel
+ );
+ SET channelid_ = LAST_INSERT_ID();
+ SET added_ = 1;
+ ELSE
+ UPDATE `channel`
+ SET `touched` = 1
+ WHERE ( `id` = channelid_ );
+ END IF;
+
+ SELECT channelid_ AS `id`,
+ added_ AS `added`;
+END
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE PROCEDURE `ftInsertFilm`(
+ _channelid INT(11),
+ _showid INT(11),
+ _title VARCHAR(255),
+ _search VARCHAR(255),
+ _aired TIMESTAMP,
+ _duration TIME,
+ _size INT(11),
+ _description LONGTEXT,
+ _website VARCHAR(384),
+ _url_sub VARCHAR(384),
+ _url_video VARCHAR(384),
+ _url_video_sd VARCHAR(384),
+ _url_video_hd VARCHAR(384),
+ _airedepoch INT(11)
+)
+BEGIN
+ DECLARE id_ INT;
+ DECLARE added_ INT DEFAULT 0;
+
+ SELECT `id`
+ INTO id_
+ FROM `film` AS f
+ WHERE ( f.channelid = _channelid )
+ AND
+ ( f.showid = _showid )
+ AND
+ ( f.url_video = _url_video );
+
+ IF ( id_ IS NULL ) THEN
+ INSERT INTO `film` (
+ `channelid`,
+ `showid`,
+ `title`,
+ `search`,
+ `aired`,
+ `duration`,
+ `size`,
+ `description`,
+ `website`,
+ `url_sub`,
+ `url_video`,
+ `url_video_sd`,
+ `url_video_hd`,
+ `airedepoch`
+ )
+ VALUES (
+ _channelid,
+ _showid,
+ _title,
+ _search,
+ IF(_aired = "1980-01-01 00:00:00", NULL, _aired),
+ IF(_duration = "00:00:00", NULL, _duration),
+ _size,
+ _description,
+ _website,
+ _url_sub,
+ _url_video,
+ _url_video_sd,
+ _url_video_hd,
+ _airedepoch
+ );
+ SET id_ = LAST_INSERT_ID();
+ SET added_ = 1;
+ ELSE
+ UPDATE `film`
+ SET `touched` = 1
+ WHERE ( `id` = id_ );
+ END IF;
+ SELECT id_ AS `id`,
+ added_ AS `added`;
+END
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE PROCEDURE `ftInsertShow`(
+ _channelid INT(11),
+ _show VARCHAR(255),
+ _search VARCHAR(255)
+)
+BEGIN
+ DECLARE showid_ INT(11);
+ DECLARE touched_ INT(1);
+ DECLARE added_ INT(1) DEFAULT 0;
+
+ SELECT `id`,
+ `touched`
+ INTO showid_,
+ touched_
+ FROM `show`
+ WHERE ( `show`.`channelid` = _channelid )
+ AND
+ ( `show`.`show` = _show );
+
+ IF ( showid_ IS NULL ) THEN
+ INSERT INTO `show` (
+ `channelid`,
+ `show`,
+ `search`
+ )
+ VALUES (
+ _channelid,
+ _show,
+ _search
+ );
+ SET showid_ = LAST_INSERT_ID();
+ SET added_ = 1;
+ ELSE
+ UPDATE `show`
+ SET `touched` = 1
+ WHERE ( `id` = showid_ );
+ END IF;
+
+
+ SELECT showid_ AS `id`,
+ added_ AS `added`;
+END
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE PROCEDURE `ftUpdateEnd`(
+ _full INT(1)
+)
+BEGIN
+ DECLARE del_chn_ INT DEFAULT 0;
+ DECLARE del_shw_ INT DEFAULT 0;
+ DECLARE del_mov_ INT DEFAULT 0;
+ DECLARE cnt_chn_ INT DEFAULT 0;
+ DECLARE cnt_shw_ INT DEFAULT 0;
+ DECLARE cnt_mov_ INT DEFAULT 0;
+
+ IF ( _full = 1 ) THEN
+ SELECT COUNT(*)
+ INTO del_chn_
+ FROM `channel`
+ WHERE ( `touched` = 0 );
+
+ SELECT COUNT(*)
+ INTO del_shw_
+ FROM `show`
+ WHERE ( `touched` = 0 );
+
+ SELECT COUNT(*)
+ INTO del_mov_
+ FROM `film`
+ WHERE ( `touched` = 0 );
+
+ DELETE FROM `show`
+ WHERE ( `show`.`touched` = 0 )
+ AND
+ ( ( SELECT SUM( `film`.`touched` ) FROM `film` WHERE `film`.`showid` = `show`.`id` ) = 0 );
+
+ DELETE FROM `film`
+ WHERE ( `touched` = 0 );
+ ELSE
+ SET del_chn_ = 0;
+ SET del_shw_ = 0;
+ SET del_mov_ = 0;
+ END IF;
+
+ SELECT del_chn_ AS `del_chn`,
+ del_shw_ AS `del_shw`,
+ del_mov_ AS `del_mov`,
+ cnt_chn_ AS `cnt_chn`,
+ cnt_shw_ AS `cnt_shw`,
+ cnt_mov_ AS `cnt_mov`;
+END
+ """ )
+ self.conn.commit()
+
+ cursor.execute( """
+CREATE PROCEDURE `ftUpdateStart`(
+ _full INT(1)
+)
+BEGIN
+ DECLARE cnt_chn_ INT DEFAULT 0;
+ DECLARE cnt_shw_ INT DEFAULT 0;
+ DECLARE cnt_mov_ INT DEFAULT 0;
+
+ IF ( _full = 1 ) THEN
+ UPDATE `channel`
+ SET `touched` = 0;
+
+ UPDATE `show`
+ SET `touched` = 0;
+
+ UPDATE `film`
+ SET `touched` = 0;
+ END IF;
+
+ SELECT COUNT(*)
+ INTO cnt_chn_
+ FROM `channel`;
+
+ SELECT COUNT(*)
+ INTO cnt_shw_
+ FROM `show`;
+
+ SELECT COUNT(*)
+ INTO cnt_mov_
+ FROM `film`;
+
+ SELECT cnt_chn_ AS `cnt_chn`,
+ cnt_shw_ AS `cnt_shw`,
+ cnt_mov_ AS `cnt_mov`;
+END
+ """ )
+ self.conn.commit()
+
+ cursor.close()
+ self.logger.info( 'Database creation successfully completed' )
+ except mysql.connector.Error as err:
+ self.logger.error( '=== DATABASE CREATION ERROR: {} ===', err )
+ self.notifier.ShowDatabaseError( err )
+ try:
+ if dbcreated:
+ cursor.execute( 'DROP DATABASE `{}`'.format( self.settings.database ) )
+ self.conn.commit()
+ if cursor is not None:
+ cursor.close()
+ del cursor
+ if self.conn is not None:
+ self.conn.close()
+ self.conn = None
+ except mysql.connector.Error as err:
+ # should never happen
+ self.conn = None