# -*- coding: utf-8 -*-
from __future__ import (unicode_literals, division, absolute_import,
                        print_function)
__license__   = 'GPL v3'
__copyright__ = '2014, DaltonST <DaltonShiTzu@outlook.com>'

__my_version__ = "3.6.26"     #still contains all CREATEs and seeds for user failsafe.
import os, sys
#import sqlite3 #sqlite3.dll bundled with Calibre is too outdated for this particular module
#from sqlite3 import IntegrityError, OperationalError, Row
import apsw  #required in this module because sqlite3.dll core function "instr" not available otherwise
from calibre.library.database import LibraryDatabase
import datetime, re, sre_constants
from calibre.db.backend import DB
from calibre import isbytestring, force_unicode, prints
from calibre.constants import iswindows, filesystem_encoding, preferred_encoding
from Queue import Empty, Queue
from calibre.gui2.threaded_jobs import ThreadedJob, BaseJob
from calibre.utils.logging import Log as log
from calibre.gui2 import error_dialog, info_dialog
import codecs
from time import sleep
import time
import unicodedata
from copy import deepcopy


myquotes = "\""
mysinglequote = "\'"
mycsvcolumnnulls = "\,''"
mynothing = ""
mynull = None
my_terminate_early = False
s_factual = "Factual"
my_type = s_factual
s_anythingelse = "ANYTHING_ELSE"
s_convert_comma = " "

notifications = Queue()

missing_tag_combinations = []     #for export of tag combinations for books with no applicable rules

book_new_genre_dict = {}            #dictionary still in utf8 of final genre for each selected book
my_book_tags = []               #list of books with tags.  multiple rows per book normal.
my_book_ids = []

my_rules_found = []            #working list of rules found for a specific book
rule_list = []

my_search_list_of_tag_rows = []

my_nonfiction_languages = []    #list of keywords meaning "nonfiction" in any language that cvs can import (not Chinese, etc.)

x_tag_keyword_1 = ""    #tags to genre rule keywords for boolean logic
y_tag_keyword_2 = ""
z_tag_keyword_3 = ""
a_tag_keyword_4 = ""
b_tag_keyword_5 = ""

varxyzab = False
my_current_book_id = "000000"

my_finalized_concat = "+"
is_good_rule = "NO"

n_rules_fiction = 0
n_rules_factual = 0
n_rules_author = 0
n_factual_books = 0
n_book_ids = 0
n_nf_keywords = 0
n_missing_tag_rules = 0

tmp_fiction_genre = "NONE"
tmp_factual_genre = "NONE"
rules_left = 0

custom_table = str("custom_column_X")
custom_id = 999
books_custom_column_X_link_str = str("books_custom_column_X_link")

from calibre_plugins.quarantine_and_scrub.heading import log_heading_common
header_s1 = None
header_s2 = None
header_s3 = None
header_s4 = None
header_s5 = None

# ---------------------------------------------------------------------------------------
#
#    Derives Genres from Boolean Tag Rules and Author Rules Using Q&S Tables
#
# ---------------------------------------------------------------------------------------

def main_derive_genres(self, guidb, book_ids, results_status, log=None, abort=None, notifications=True):
    global header_s1
    global header_s2
    global header_s3
    global header_s4
    global header_s5
    global my_terminate_early
    global mynothing
    global n_book_ids
    global n_rules_fiction
    global n_rules_factual
    global n_rules_author
    global n_factual_books
    global n_nf_keywords
    global n_missing_tag_rules
    global my_book_ids
    global book_new_genre_dict        #dictionary still in utf8 of final genre for each selected book that had a matched and valid rule


    my_book_ids = []
    for item in book_ids:
        my_book_ids.append(item)

    n_book_ids = len(book_ids)

    header_s3 = ("Q&S: Deriving Genres for " + str(n_book_ids) + " Book(s)")
    notifications.put((0.01, 'Beginning Deriving Genres'))

   #----------------------------------------------------------------------------------------------------------------
    db = guidb
    path = db.library_path
    __printsafe(path)
    if isbytestring(path):
        path = path.decode(filesystem_encoding)
    path = path.replace(os.sep, '/')
    path = os.path.join(path, 'metadata.db')
    path = path.replace(os.sep, '/')
    __printsafe(path)
    log(path)
    __printsafe(path)
    try:
        my_db =apsw.Connection(path)
        #my_db = sqlite3.connect(path)
    except Exception as e:
        __printsafe(str(e))
        log(str(e))
        raise e
        return

    my_cursor = my_db.cursor()

    #s = sqlite3.sqlite_version  #e.g. 3.6.21
    header_s1 =  str("SQLite Version: " + str(apsw.SQLITE_VERSION_NUMBER) + "  [APSW]")   #e.g. 3.8.4

    mysql = str("PRAGMA main.locking_mode=EXCLUSIVE;")
    my_cursor.execute(mysql)  #apsw
    header_s2 = mysql

    log_heading_common(log,header_s1,header_s2,header_s3,header_s4,header_s5)

    mysql = "PRAGMA main.busy_timeout = 5000;"      #PRAGMA busy_timeout = milliseconds;  (obviously just for this connection)
    my_cursor.execute(mysql)

    log(" ")
    log("Q&S Derive Genres is controlled by 4 DG tables within Q&S that are User-Maintained: ")
    log("...........    _dg_nf_language_keywords  ")
    log("...........    _dg_genre_tag_rules_factual ")
    log("...........    _dg_genre_tag_rules_fiction ")
    log("...........    _dg_genre_author_rules       ")
    log(" ")
    log(" ")
    log("Q&S DG uses Real Tags, not Work Tags, so finalize Real Tags prior to execution.")
    log(" ")
    log("Q&S DG adds missing Tag Rule Combinations to DG table _dg_missing_tag_rules. ")
    log(" ")
    log("You should use table _dg_missing_tag_rules to help you create new Tag Rules.")
    log(" ")
    log("You should delete rows in table _dg_missing_tag_rules that no longer are useful to you.")
    log("-----------------------------------------------------------------------------------------------")
    log("-----------------------------------------------------------------------------------------------")

    #in case they do not exist already
    Create_DG_Tables_If_Not_Exist(my_db, my_cursor, log)

    #in case they are empty
    Seed_User_Maintained_Rules_Tables(my_db,my_cursor,log)

    #now create an SQLite user function in Python to make utf8 text all lower case for later matching of Tags to Tag Rule Keywords
    Create_SQLite_User_Function(my_db, my_cursor, log)

    Validate_User_Maintained_Rules_Tables(my_db,my_cursor,log)

    my_terminate_early = False

    #custom_columns table: get values for tables for configured field for genre
    my_terminate_early = Get_Custom_Table_Name(my_db,my_cursor,log)
    if my_terminate_early:
        log("Terminating Early Due To Failures and/or Errors")
        my_db.close()
        return

    book_new_genre_dict = {}
    del book_new_genre_dict
    book_new_genre_dict = {}


    #Start...


    DG_Control(self, my_db, my_cursor, my_book_ids, notifications, log)


    Count_Rules_Available(self, my_db, my_cursor,  my_book_ids, notifications, log)

    log("-----------------------------------------------------------------------------------------------")
    log("-----------------------------------------------------------------------------------------------")
    #Finished...
    s =  ("Number of Selected Books to Process:                             " + "|" + str(n_book_ids)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)

    s = ("Number of Rules for Fiction/Poetry Processed:                    "  + "|" +  str(n_rules_fiction)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    s = ("Number of Rules for Factual Processed:                           " + "|" +  str(n_rules_factual)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    s = ("Number of Rules for Authors Processed:                           " + "|" +  str(n_rules_author)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    s = ("Number of Multi-Language Factual Keywords:                       " + "|" +  str(n_nf_keywords)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)

    s = ("Number of Books for Which Tags Were Gathered:                    " + "|" +  str(n_book_ids)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    s = ("Number of Factual Books Identified:                              " + "|" +  str(n_factual_books)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    n_fiction_books = n_book_ids - n_factual_books
    s = ("Number of Non-Factual Books Identified:                          " + "|" +  str(n_fiction_books)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    n_new_genres = len(book_new_genre_dict)
    s = ("Number of New Genres Derived from Rules:                         " + "|" +  str(n_new_genres)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    n_failures = n_book_ids - n_new_genres
    s = ("Number of Books With No Applicable Rules:                        " + "|" +  str(n_failures)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    s = ("Number of Missing Tag Rules in _dg_missing_tag_rules:            " + "|" +  str(n_missing_tag_rules)  )
    results_status.append(s)
    s = s.replace("|", mynothing,1)
    log(s)
    log("-----------------------------------------------------------------------------------------------")
    log("-----------------------------------------------------------------------------------------------")


    _purge_work_tables(my_db,my_cursor,log)     #new version 3.6.25

    if not my_terminate_early:
        notifications.put((0.99, 'Genre Derivation'))
        log("Genre Derivation ended normally")
        my_db.close()
    else:
        log("Terminating Early Due To Failures and/or Errors")
        my_db.close()

    return results_status

    #----------------------------------------------------------------------------------------------------------------
def Count_Rules_Available(self, my_db, my_cursor,  my_book_ids, notifications, log):
    global n_rules_fiction
    global n_rules_factual
    global n_rules_author
    global n_nf_keywords
    global n_missing_tag_rules

    mysql = "SELECT Count(*) FROM _dg_genre_tag_rules_fiction"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    n_rules_fiction = str(count1)

    mysql = "SELECT Count(*) FROM _dg_genre_tag_rules_factual"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    n_rules_factual = str(count1)

    mysql = "SELECT Count(*) FROM _dg_genre_author_rules"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    n_rules_author = str(count1)

    mysql = "SELECT Count(*) FROM _dg_nf_language_keywords"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    n_nf_keywords = str(count1)

    mysql = "SELECT Count(*) FROM _dg_missing_tag_rules"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    n_missing_tag_rules = str(count1)


    #----------------------------------------------------------------------------------------------------------------
def DG_Control(self, my_db, my_cursor,  my_book_ids, notifications, log):


    global my_terminate_early

    notifications.put((0.02, 'Deriving Genres in Q&S'))
    Populate_DG_Book_Tables(my_db, my_cursor, notifications, log)
    Book_Processing_Control(my_db, my_cursor, notifications, log)
    if not my_terminate_early:
        notifications.put((0.99, 'Genre Derivation Complete'))

    #------------------------------------------------------------------------------------------------------------------------------
def Populate_DG_Book_Tables(my_db, my_cursor, notifications, log):


    notifications.put((0.02, 'Finding Factual Books in Selection'))

    Create_dg_books_factual(my_db, my_cursor, notifications, log)


    notifications.put((0.03, 'Finding Author Names for Books in Selection'))

    Create_dg_books(my_db, my_cursor, notifications, log)


    notifications.put((0.04, 'Finding Tag Names for Selected Books'))

    Create_dg_books_tagnames(my_db, my_cursor, notifications, log)


    notifications.put((0.08, 'Finding Tag Rules for Specific Books'))

    Create_dg_books_tagrules(my_db, my_cursor, notifications, log)


    notifications.put((0.60, 'Now Deriving Genres for Each Selected Book'))


    #-----------------------------------------------------------------------------------------------------------------------------
def Create_dg_books_factual(my_db, my_cursor, notifications, log):

    #Use sql to identify which books are factual from the list of books sent by ui.py, and insert their id's into this table

    global my_book_ids
    global n_factual_books
    global my_nothing

    n_factual_books = 0

    tmp_book_id = "00000"

    #notifications.put((0.07, 'Creating List of Factual Books'))

    my_commit_count = 0
    my_cursor.execute("begin")  #apsw
    for row in my_book_ids:
        tmp_book_id = row
        mysql = "INSERT OR IGNORE INTO _dg_books_factual SELECT id, book, tag, tag, tag FROM books_tags_link "
        mysql = mysql + "WHERE books_tags_link.book = '" + tmp_book_id + "'  ; "
        try:
            my_cursor.execute (mysql)
            my_commit_count =  my_commit_count + 1
            if   my_commit_count >= 200:
                my_cursor.execute("commit")  #defer for performance
                sleep(.001)  #to avoid db busy/locked error when python is running faster than sqlite
                my_cursor.execute("begin")  #apsw
                my_commit_count = 0
        except Exception as e:
            raise e
            log(str(e))
            my_db.close()
    #END FOR
    if my_commit_count > 0:
        my_cursor.execute("commit")

    sleep(0.1)

    try:
        my_cursor.execute("commit")    #to avoid an outstanding begin transaction causing failures
    except:
        pass

    #now, update _dg_books_tags.name with the real name of the tag id temporarily stored there
    my_cursor.execute("begin")  #apsw
    mysql = "UPDATE _dg_books_factual SET name = (SELECT name FROM tags "
    mysql = mysql + "WHERE tags.id = _dg_books_factual.tag) WHERE _dg_books_factual.id > 0 "
    try:
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
        sleep(.001)  #to avoid db busy/locked error when python is running faster than sqlite
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()

    #sqlite user function
    my_cursor.execute("begin")  #apsw
    mysql = "UPDATE _dg_books_tagnames SET name = (make_utf8_lowercase(name) );"
    try:
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()
    #then, update the rows in _dg_books_tags via an inner join equivalent with nf_language_keywords (i.e. the factual keywords)
    my_cursor.execute("begin")  #apsw
    mysql = "UPDATE _dg_books_factual SET factual = (SELECT nf_keyword FROM _dg_nf_language_keywords "
    mysql = mysql + "WHERE _dg_nf_language_keywords.nf_keyword = _dg_books_factual.name) WHERE _dg_books_factual.id > 0 "
    try:
        my_cursor.execute (mysql)
        my_commit_count =  my_commit_count + 1
        if  my_commit_count >= 200:
            my_cursor.execute("commit")  #defer for performance
            sleep(.001)  #to avoid db busy/locked error when python is running faster than sqlite
            my_commit_count = 0
            my_cursor.execute("begin")  #apsw
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()

    if my_commit_count > 0:
        my_cursor.execute("commit")

    sleep(1.0)

    try:
        my_cursor.execute("commit")    #to avoid an outstanding begin transaction causing failures
    except:
        pass

    #now, delete any rows that have no column "factual" value
    my_cursor.execute("begin")  #apsw
    mysql = "DELETE FROM _dg_books_factual WHERE _dg_books_factual.factual is NULL "
    try:
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
        sleep(1.0)  #to avoid db busy/locked error when python is running faster than sqlite
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()

    #just to count the remaining rows in the table for stats
    mysql = "SELECT id FROM _dg_books_factual WHERE id > 0 "
    try:
        tmp_rules = []  #in case zero rows fetched
        my_cursor.execute (mysql)
        tmp_rules = my_cursor.fetchall() #will get the (remaining) rows from the query
        if tmp_rules:
            n_factual_books = len(tmp_rules)
            del tmp_rules
        else:
            n_factual_books = 0
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()


    #so now, to find out if a book is factual or not factual, simply interrogate table _dg_books_factual for
    #the mere existance in it of a particular book

    #-----------------------------------------------------------------------------------------------------------------------------
def Determine_If_Book_Is_Factual(my_db, my_cursor, log):

    global my_current_book_id
    global my_type
    global s_factual


    my_type = "something else"
    tmp_book = my_current_book_id

    mysql = "SELECT * from _dg_books_factual WHERE book = '" + tmp_book + "' ;"
    try:
        my_cursor.execute (mysql)
        tmp_rows = my_cursor.fetchall() #will get the (remaining) rows from the query
        if tmp_rows:
                n_rows = len(tmp_rows)
                del tmp_rows
        else:
            n_rows = 0
        if n_rows > 0:
          my_type = s_factual
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()

    #---------------------------------------------------------------------------------------------------------------------------------
def Create_dg_books(my_db, my_cursor, notifications, log):
    #must be created AFTER _dg_books_factual is built since it uses that table in this function...

    global my_book_ids
    global my_nothing

    my_commit_count = 0

    #create the _dg_books table
    my_cursor.execute("begin")  #apsw
    for row in my_book_ids:
        sleep(0.001)
        tmp_book = row
        try:
            try:
                n_rows = 0
                my_type = "something"
                mysql = "SELECT book FROM _dg_books_factual WHERE book = '" + tmp_book + "' "
                my_cursor.execute (mysql)
                tmp_rows = my_cursor.fetchall()
                if tmp_rows:
                        n_rows = len(tmp_rows)
                        del tmp_rows
                else:
                    n_rows = 0
            except Exception as e:
                raise e
                log(str(e))
                my_db.close()

            if n_rows > 0:
                my_type = "FACTUAL"
            else:
                my_type = "FICTION"


            try:
                mysql = "INSERT OR IGNORE INTO _dg_books (book,type) VALUES('" + tmp_book + "','" + my_type + "' );"
                my_cursor.execute (mysql)
                my_commit_count = my_commit_count +1
                if my_commit_count >= 500:
                    my_cursor.execute("commit")  #defer for performance
                    my_commit_count = 0
                    sleep(0.5)
                    my_cursor.execute("begin")  #apsw
            except Exception as e:
                raise e
                log(str(e))
                my_db.close()
        except Exception as e:
            raise e
            log(str(e))
            my_db.close()
    #END FOR

    try:
        my_cursor.execute("commit")        #avoid hanging transaction whether commit needed or not
    except:
        pass


   #------------------------------------------------------------------------------------------------------------------------------------
def Create_dg_books_tagnames(my_db, my_cursor, notifications, log):

    notifications.put((0.08, 'Creating List of Tag Names by Book'))

    global my_book_ids

    tmp_book_id = '00000'

    try:
         my_cursor.execute("commit")     #avoid failure due to outstanding begin transaction
    except:
        pass

    my_commit_count = 0
    my_cursor.execute("begin")  #apsw
    for row in my_book_ids:
        sleep(.001)
        tmp_book_id = row
        mysql = "INSERT OR IGNORE INTO _dg_books_tagnames SELECT id, book, tag, tag FROM books_tags_link "
        mysql = mysql + "WHERE books_tags_link.book = '" + tmp_book_id + "'  ; "
        try:
            my_cursor.execute (mysql)
            my_commit_count = my_commit_count +1
            if my_commit_count >= 200:
                my_cursor.execute("commit")
                my_commit_count = 0
                sleep(.001)  #to avoid db busy/locked error when python is running faster than sqlite
                my_cursor.execute("begin")  #apsw
            else:
                pass
        except Exception as e:
            raise e
            log(str(e))
            my_db.close()
    #END FOR

    if my_commit_count > 0:
        try:
            my_cursor.execute("commit")
            my_commit_count = 0
        except Exception as e:
            raise e
            log(str(e))
            my_db.close()
    else:
        pass

    sleep(0.5)

    try:
         my_cursor.execute("commit")     #avoid failure due to outstanding begin transaction
    except:
        pass

    #now, update _dg_books_tagnames with the real user friendly name of the tag id temporarily stored there
    my_cursor.execute("begin")  #apsw
    mysql = "UPDATE _dg_books_tagnames SET name = (SELECT name FROM tags "
    mysql = mysql + "WHERE tags.id = _dg_books_tagnames.tag) WHERE _dg_books_tagnames.id is not null "
    try:
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
        sleep(1.0)  #to avoid db busy/locked error when python is running faster than sqlite
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()

   #sqlite user function
    my_cursor.execute("begin")  #apsw
    mysql = "UPDATE _dg_books_tagnames SET name = (make_utf8_lowercase(name) );"
    try:
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
    except Exception as e:
        raise e
        log(str(e))
        my_db.close()



    #--------------------------------------------------------------------------------------------------------------
def Create_dg_books_tagrules(my_db, my_cursor, notifications, log):

    notifications.put((0.10, 'Sifting Rules for Factual Books'))

    global my_book_ids

    q = len(my_book_ids)
    t_to_sleep = float(q * 0.0001)
    if t_to_sleep < 3.0 :
        t_to_sleep = 3.0
    sleep(t_to_sleep)  #to avoid db busy/locked error when python is running faster than sqlite

    #For this to work properly, the Tags in _dg_books_tagnames MUST have been converted to lower case
    #via the user-defined SQLite function executed on table _dg_books_tagnames previously.  Otherwise,
    # "Vampire" would not match to "vampire".

    try:
         my_cursor.execute("commit")     #avoid failure due to outstanding begin transaction
    except:
        pass

    my_cursor.execute("begin")  #apsw
    mysql = "INSERT OR IGNORE INTO _dg_books_tagrules SELECT * from __dg_match_tags_and_keywords_factual ; "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    notifications.put((0.35, 'Sifting Rules for Fiction Books'))

    my_cursor.execute("begin")  #apsw
    mysql = "INSERT OR IGNORE INTO _dg_books_tagrules SELECT * from __dg_match_tags_and_keywords_fiction  ; "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    #update all rows of _dg_books_tagrules to change column dummy to  mean "ignore".
    #my_cursor.execute("begin")  #apsw
    #mysql = "UPDATE _dg_books_tagrules SET dummy = '-' ;"
    #Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    sleep(t_to_sleep)  #to avoid db busy/locked error when python is running faster than sqlite

   #-----------------------------------------------------------------------------------------------------------------------------
def Book_Processing_Control(my_db, my_cursor, notifications, log):

    #this is the fun part.  analyze each book's tags and compare them to the various rules, creating a new output list of books & genre.

    global my_search_list_of_tag_rows         #raw utf-8 directly via sqlite from metadata.db
    global my_rules_found
    global x_tag_keyword_1
    global y_tag_keyword_2
    global z_tag_keyword_3
    global a_tag_keyword_4
    global b_tag_keyword_5
    global my_finalized_concat
    global is_good_rule
    global n_book_ids
    global my_type
    global my_book_ids
    global my_current_book_id
    global mynothing
    global book_new_genre_dict


    s = str(n_book_ids)
    t = ("Books in Process: " + s)

    my_index = 0
    my_selected_total = len(my_book_ids)
    if my_selected_total == 0:
        #bad list of books from ui.py
        print("Error.  No books selected.")
        log("Error.  No books selected.")
        my_terminate_early = "YES"
    else:
        while my_index < my_selected_total:  #<<<========== MAIN LOOP============>>>

            n_percent_complete = float(0.60 + (0.4*((my_index + 1) / (my_selected_total))))
            notifications.put((n_percent_complete, t))

            #New Current Book:     e..g. 12345

            my_current_book_id = my_book_ids[my_index]  #<<<==== New Current Book
            my_current_book_id = str(my_current_book_id)
            my_current_book_id = my_current_book_id.encode("ascii", "ignore")
            my_current_book_id = my_current_book_id.replace(" ", mynothing, 20)


            #-------------------------------------------
            #initialize variables for new my_current_book_id in main loop
            del my_rules_found
            my_rules_found = []
            x_tag_keyword_1 = mynothing
            y_tag_keyword_2 = mynothing
            z_tag_keyword_3 = mynothing
            a_tag_keyword_4 = mynothing
            b_tag_keyword_5 = mynothing
            my_finalized_concat = "+"
            is_good_rule = "NO"
            del my_search_list_of_tag_rows
            my_search_list_of_tag_rows = []
            my_type = "somethingelse"
            #--------------------------------------------


            Determine_If_Book_Is_Factual(my_db, my_cursor, log)

            Rule_Search_and_Selection_Control_Generic(my_db, my_cursor, my_current_book_id, my_type, my_search_list_of_tag_rows,notifications, log)

            my_index = my_index + 1
        #END  WHILE...
        notifications.put((0.98, 'Updating New Genre(s)'))

        n = len(book_new_genre_dict)
        if n > 0:
            Update_Custom_Column_Genre(my_db, my_cursor, log)
        else:
            log("No Genres to Update for Selected Books")
    #END IF

    try:
        my_cursor.execute("begin")  #apsw
        mysql = str("DELETE FROM _dg_books ")
        my_cursor.execute(mysql)   #apsw
        mysql = str("DELETE FROM _dg_books_factual ")
        my_cursor.execute(mysql)   #apsw
        mysql = str("DELETE FROM  _dg_books_tagnames")
        my_cursor.execute(mysql)   #apsw
        mysql = str("DELETE FROM  _dg_books_tagrules")
        my_cursor.execute(mysql)   #apsw
        my_cursor.execute("commit")  #apsw
    except Exception as e:
        log("ERROR in deleting all transient table data that is no longer needed.")
        log(str(e))
        try:
            my_cursor.execute("commit")  #apsw
        except:
            pass


    #-----------------------------------------------------------------------------------------------------------------------------------------------------------

def Rule_Search_and_Selection_Control_Generic(my_db, my_cursor, my_current_book_id,  my_type, my_search_list_of_tag_rows, notifications, log):

    global book_new_genre_dict        #dictionary still in utf8 of final genre for each selected book that had a matched and valid rule
    global mynothing
    global my_rules_found
    global my_temp_genre
    global tmp_fiction_genre
    global tmp_factual_genre
    global rules_left
    global s_factual
    global utf8_to_convert

    tmp_book_genre = " "
    tmp_list_longest = []
    tmp_book = "0"

    Generic_Narrow_Tag_Rule_Results_Using_Operators(my_db, my_cursor, my_current_book_id, log)

    n = len(my_rules_found)

    if n > 0 and rules_left > 0:  #that means that there are still, right now, rules in the narrowed list of rules retrieved via sql.  Now, pick the best genre.

        my_longest_genre = " "
        my_temp_genre = "NONE"
        tmp_book_genre = "NONE"
        s = "NONE"
        my_selected_total = len(my_rules_found)
        my_index = 0
        while my_index < my_selected_total:
            #now extract the new_genre from the rest of the tag rule
            #_dg_books_tagrules:  "1767","FICTION", "xxxxxxx", "8",   "Ficción:Ciencia","ciencia","OR ","ficción:ciencia","AND","español","NONE","NONE","NONE","NONE"
            #                                    book     type             ignore    rule_id   new_genre      kw1          op1         kw2         op2       kw3          op3            kw4       op4          kw5
            #                   index:          0          1                   2              3                     4                 5              6              7           8               9              10            11             12              13
            z = my_rules_found[my_index]   #still utf8
            z = str(z)
            tmp_list_longest =z.split(",")    #still utf8
            #zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
            #s = tmp_list_longest[4]  #<<<=== the new_genre field is list row index 4; ignore all other columns        #original derive genres using csv files
            s = tmp_list_longest[3]  #<<<=== the new_genre field is list row index 3; ignore all other columns          #new q&S derive genres using tables
            #zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
            q = s.find(" u'")
            if q == 0:
                s = s.replace(" ", mynothing, 1)
            q = s.find(" u'")
            if q == 0:
                s = s.replace(" ", mynothing, 1)
            q = s.find("\\")
            w = s.find(" ")
            if q >= 0 and w > q: #e.g. u'N\xxx\xxx\xxx\xxx  yyyyyy" i.e., a rule's new_genre along with the next field, tag_keyword_1
                s1 = s.split(" ")
                s = s1[0]               #e.g. u'N\xxx\xxx\xxx\xxx
            s = s.replace(",", mynothing, 4)   #still utf8
            if (len(my_longest_genre)) < (len(s)):  #the longest genre wins, since to be longer means (in theory) to be more specific
                my_longest_genre = s                        #ENHANCEMENT: SOME OTHER ALGORITHM FOR PICKING THE BEST RULE?
            my_index = my_index + 1
        #END WHILE

        tmp_book_genre = my_longest_genre   #bingo

    else: #no tag rules left (or no tags at all in the first place), so look for rules based on author, not based on tags.

        Accumulate_Missing_Tag_Combinations(my_db, my_cursor, my_current_book_id, log)

        tmp_fiction_genre = "NONE"
        tmp_factual_genre = "NONE"
        tmp_book_genre = "NONE"

        Search_Table_dg_genre_author_rules(my_db, my_cursor, my_current_book_id, notifications, log)

        if my_type == s_factual:
            tmp_book_genre = tmp_factual_genre  #still in utf8
        else:
            tmp_book_genre = tmp_fiction_genre  #still in utf8
    #END IF

    # it is very likely that tmp_book_genre == "NONE" upon return from search table zgenre author rules

    tmp_book = my_current_book_id

    n = len(tmp_book_genre)

    p = tmp_book_genre.find("NONE")


    if ((tmp_book_genre <> "NONE") and (tmp_book_genre <> mynothing) and (tmp_book_genre > " ") and (n > 0) and (p < 0)):

        try:  #dictionary is always pure unicode utf8
            tmp_book = unicode(my_current_book_id)
            tmp_book_genre = str(tmp_book_genre)
            tmp_book_genre = str(Strip_UTF8_To_String(tmp_book_genre))
            tmp_book_genre = str(Strip_Parens_and_Commas(tmp_book_genre))
            tmp_book_genre = unicode(tmp_book_genre)
            book_new_genre_dict.update({tmp_book: tmp_book_genre})
        except Exception as e:
            log("error in add to dictionary")
            log(str(e))
            pass
    else:
        pass

    del tmp_list_longest


    #------------------------------------------------------------------------------------------------------------------------------------

def Strip_Parens_and_Commas(u_string):
    #remove only parentheses and commas. nothing else.  at all.

    global mynothing

    u_string = str(u_string)
    u_string = u_string.replace("(", mynothing, 2)
    u_string = u_string.replace(")", mynothing, 2)
    u_string = u_string.replace(",", mynothing, 2)

    #print(u_string)

    return u_string

    #------------------------------------------------------------------------------------------------------------------------------------
def Generic_Narrow_Tag_Rule_Results_Using_Operators(my_db, my_cursor, my_current_book_id, log):

    global mynothing
    global is_good_rule
    global my_finalized_concat
    global my_rules_found
    global rules_left
    global my_nothing

    rmv_list = []
    tmp_list = []
    tmp_list_copy1 = []
    tmp_listx = []

    rules_left = 0

    rule_list = []
    del rule_list
    rule_list = []

    my_rules = []

    #fetch all of the rules for the current book id from table _dg_books_tagrules
    mysql = "SELECT * FROM _dg_books_tagrules WHERE book = '" + my_current_book_id + "' ;"
    try:
        my_cursor.execute (mysql)
        my_rules = my_cursor.fetchall() #will get the (remaining) rows from the query
    except:
        pass

    my_rules_found = my_rules
    rule_list = my_rules
    del my_rules

    n = len(rule_list)
    i = 0
    while i < n:        #<<<=== LOOP THROUGH ALL RULES FOR CURRENT BOOK IN MAIN LOOP========================
        myline = rule_list[i]       #utf8

        __printsafe("a new tag rule for the current book to analyze: ", myline)

        rmv = myline                #for .removing(fmv) from my_rules_found as necessary at the end of narrowing
        tmp_row = myline         #both are utf8 at this point

        try:
            tmp_row.decode('utf8').encode('iso8859-15')  #<type 'unicode'> to <type 'str'>
        except:
            tmp_row = Strip_UTF8_To_String(tmp_row) #does not remove commas or spaces

        #do not allow the commas to be removed prior to the split...

        tmp_listx = []
        del tmp_listx
        tmp_listx = []
        tmp_listx = tmp_row.split(",")   #split returns a List of the single rule, so it can be analyzed within a loop. destroyed during parsing.

        del tmp_list
        tmp_list = []

        w1 = 99  #index of book
        w2 = 99  #index of rule number
        windex = 0
        for item in tmp_listx:  #an item is a line of a single split rule  list
            appnd = Strip_UTF8_To_String(item) #does not remove commas or spaces
            appnd = appnd.replace(",", mynothing, 4)
            appnd = appnd.replace(" ", mynothing, 20)
            if not appnd.isdigit():  #the book and the rule_id  are integers  (so now have 2 fewer items in the list)
                if (appnd == "FACTUAL" or appnd == "FICTION"):  #the Type column re: the type of book the book is...
                    pass
                else:
                    if appnd == "NONE":
                        pass
                    else:
                        if windex == (w2 + 1): #the new_genre
                            __printsafe("deleting the new genre: ", appnd)
                            pass
                        else:
                            if windex >= (w2 + 2): #keyword 1
                                tmp_list.append(appnd) #lines of a single split rule
                                __printsafe("line of a single split rule being appended: ", appnd)
            else:
                if w1 == 99:
                    w1 = windex
                else:
                    if w2 == 99:
                        w2 = windex
                pass
            windex = windex + 1
        #END FOR

        del tmp_listx

        del tmp_list_copy1
        tmp_list_copy1 = []
        tmp_list_copy1 = deepcopy(tmp_list)  #lines of a single split rule


        Concatenate_Opererators(tmp_list)                        # creates my_finalized_concat e.g. ORORANDNOT or OR or ORAND etc.

        Extract_Keywords_From_Rule(tmp_list_copy1)       #logic for setting tag_keyword_1, 2, 3,4, 5 to send to Compare_Concatenated_Operators_...

        Create_my_search_list_of_tag_rows(my_db, my_cursor, my_current_book_id)

        is_good_rule = "NO"

        Compare_Concatenated_Operators_To_Rules()

        if is_good_rule <> "YES" :
            rmv_list.append(rmv)
        else:
            pass #keep the good rule

        i = i + 1
    #END WHILE

    sorted(rmv_list)
    sorted(my_rules_found)

    for item in rmv_list:
        my_rules_found.remove(item)

    del rmv_list
    del tmp_list
    del tmp_list_copy1

    rules_left = len(my_rules_found)


    #------------------------------------------------------------------------------------------------------------------------------------
def Concatenate_Opererators(tmp_list):  #line of single split rule

    global my_finalized_concat
    my_finalized_concat = "+"
    my_concat = my_finalized_concat           #at this point just the initial value of  "+"

    #note: tmp_list was  utf-8 up until now.  it will become a byte string, but then will be destroyed

    n1 = 0
    n2 = 1
    for item in tmp_list: #line of single split rule
        while n1 < n2:
            if n1 == 0:
                del tmp_list[0] #first row is the new_genre since the row number and book number were removed previously via the isnumeric() test
                n1 = n1 + 1
        #END WHILE
    #END FOR

    n2 = len(tmp_list)  #split rule list of a single rule (just keywords and operators now).  n2 has a maximum possible value of 10
    n_max_operators = 4
    n_operators_found = 0
    n1 = 0
    while (n1 < n2):  #loop through the split string (word by word) which originally was a single entire rule
        st = str(tmp_list[n1])  #split rule list for extracting operators; will be destroyed, so another copy made previously
        st = st.replace(" ", mynothing, 8)
        my_concat = my_concat.replace(" ", mynothing, 8)
        n3 = st.find("AND")
        if n3 >= 0:
            my_concat = my_concat + "AND"
            n_operators_found = n_operators_found + 1
        n3 = st.find("OR")
        if n3 >= 0:
            my_concat = my_concat + "OR"
            n_operators_found = n_operators_found + 1
        n3 = st.find("NOT")
        if n3 >= 0:
            my_concat = my_concat + "NOT"
            n_operators_found = n_operators_found + 1
        if n_operators_found > n_max_operators:
            log("ERROR: MORE THAN 4 OPERATORS FOUND.  Impossible...")
            break
        else:
            n1 = n1 + 1

    Clean_Space_Comma(my_concat)
    my_concat = my_concat.replace("+", mynothing, 2)
    my_finalized_concat = my_concat

    #                                                                                                                           print(my_finalized_concat)


    #------------------------------------------------------------------------------------------------------------------------------------
def Extract_Keywords_From_Rule(tmp_list_copy1):

        #logic for setting tag_keyword_1, 2, 3,4, 5 for a Single Tag Rule to send to Compare logic

        #Note: this changes the previous utf-8 tmp_list_copy1 strings into byte strings at this point

        global x_tag_keyword_1
        global y_tag_keyword_2
        global z_tag_keyword_3
        global a_tag_keyword_4
        global b_tag_keyword_5

        global mynothing

        my_new_kw_list = []

        x_tag_keyword_1 = "NONE"
        y_tag_keyword_2 = "NONE"
        z_tag_keyword_3 = "NONE"
        a_tag_keyword_4 = "NONE"
        b_tag_keyword_5 = "NONE"

        #now is:  'FICTION:SHAPESHIFTERS', 'fiction', 'AND', 'shapeshifters', 'OR', 'shapeshifter', 'NOT', 'werewolves', 'NOT', 'werewolf'

        n = len(tmp_list_copy1)
        i = 0
        while i < n:
            s = tmp_list_copy1[i]
            s = str(s)  #byte string now
            s = Clean_Space_Comma(s)    #4: space, comma
            s = s.replace("u'", mynothing, 4)
            s= s.replace("'", mynothing, 4)
            tmp_list_copy1[i] = s
            i = i + 1
            #                                                                                                                                                                   print(" a row of one split rule: ", s)


        #----------------------------------------------
        #now will be:   'fiction', 'AND', 'shapeshifters', 'OR', 'shapeshifter', 'NOT', 'werewolves', 'NOT', 'werewolf'  (row # and new_genre previously removed)
        #----------------------------

        i = 0
        for line in tmp_list_copy1:
            s = str(line)
            #                                                                                                                                                           print("line in tmp_list_copy1: ", s)
            n1 = s.find("AND")
            n2 = s.find("OR")
            n3 = s.find("NOT")
            if (n1 < 0 and n2 < 0 and n3 < 0 and s > " "): #ignore the boolean operators; want the keywords only
                #                                                 taken care in previous function:    if i <> 0: #delete the new_genre column by not adding it
                my_new_kw_list.append(s)
            i = i + 1

        n = len(my_new_kw_list)
        i = 0
        while i < n:
            s = my_new_kw_list[i]
            s = str(s) #normal byte string
            s = Clean_Space_Comma(s)    #4: , space, comma
            my_new_kw_list[i] = s
            i = i + 1


        keyword_count = 0
        n = 0
        mymax = len(my_new_kw_list)
        if mymax > 0:   #Should always occur...
            while (n < mymax):   #loop through the list of keywords (word by word) which originally was a single entire rule
                keyword_count = keyword_count + 1
                s =  my_new_kw_list[n]
                #                                                                                                                                   print("a new keyword: ",str(keyword_count),"  ", s)
                if keyword_count == 1 :
                    x_tag_keyword_1 = s
                elif keyword_count == 2 :
                    y_tag_keyword_2 = s
                elif keyword_count == 3 :
                    z_tag_keyword_3 = s
                elif keyword_count == 4 :
                    a_tag_keyword_4 = s
                elif keyword_count == 5 :
                    b_tag_keyword_5 = s
                n = n + 1
        else:
            pass #do nothing

        s = x_tag_keyword_1
        s = Clean_Space_Comma(s)#4:  space, comma
        x_tag_keyword_1 = s

        s = y_tag_keyword_2
        s = Clean_Space_Comma(s)#4: space, comma
        y_tag_keyword_2 = s

        s = z_tag_keyword_3
        s = Clean_Space_Comma(s)#4:  space, comma
        z_tag_keyword_3 = s

        s = a_tag_keyword_4
        s = Clean_Space_Comma(s)#4: space, comma
        a_tag_keyword_4 = s

        s = b_tag_keyword_5
        s = Clean_Space_Comma(s)#4:  space, comma
        b_tag_keyword_5 = s

        del my_new_kw_list
#-----------------------------------------------------------------------------------------------------
def Create_my_search_list_of_tag_rows(my_db, my_cursor, my_current_book_id):

    global my_nothing
    global my_search_list_of_tag_rows

    my_tags = []
    del my_tags

    #fetch all of the tags for the current book in process from _dg_books_tagnames
    mysql = "SELECT name FROM _dg_books_tagnames WHERE book = '" + my_current_book_id + "' ;"
    try:
        my_cursor.execute (mysql)
        my_tags = my_cursor.fetchall() #will get the (remaining) rows from the query
    except:
        pass

    my_search_list_of_tag_rows = []

    n = len(my_tags)
    if n > 0:
        for item in my_tags:
            appnd = str(item)
            appnd = Strip_UTF8_To_String(appnd) #does not remove commas or spaces
            appnd = appnd.replace(",", mynothing, 4)
            appnd = appnd.replace(" ", mynothing, 20)
            my_search_list_of_tag_rows.append(appnd)
            #                                                                                                                       print("appending to my search list of tag rows: ", appnd)

    #--------------------------------------------------------------------------------------------------
def Compare_Concatenated_Operators_To_Rules():

    global mynothing
    global my_type
    global is_good_rule
    global my_finalized_concat
    global varxyzab

    my_finalized_concat = my_finalized_concat.replace("'", mynothing, 10)
    my_finalized_concat = my_finalized_concat.replace(" ", mynothing, 10)
    my_finalized_concat = my_finalized_concat.replace("NONE", mynothing, 4)  #to ensure it has only real, valid boolean operators before comparison below
    my_concat = my_finalized_concat

    global x_tag_keyword_1
    global y_tag_keyword_2
    global z_tag_keyword_3
    global a_tag_keyword_4
    global b_tag_keyword_5

    x = False
    y = False
    z = False
    a = False
    b = False


    x = Search_my_search_list_of_tag_rows(x_tag_keyword_1)

    y = Search_my_search_list_of_tag_rows(y_tag_keyword_2)

    z = Search_my_search_list_of_tag_rows(z_tag_keyword_3)

    a = Search_my_search_list_of_tag_rows(a_tag_keyword_4)

    b = Search_my_search_list_of_tag_rows(b_tag_keyword_5)

    varxyzab = False
    passed_wildcard_comparison = False
    passed_wildcard_comparison = Compare_Wildcards_To_Tags(varxyzab)


    if not passed_wildcard_comparison: #not a good rule due to wildcard "*" logic
        x = False
        y = False
        z = False
        a = False
        b = False


    is_good_rule = "NO"

    '''
    print(x_tag_keyword_1)
    print(y_tag_keyword_2)
    print(z_tag_keyword_3)
    print(a_tag_keyword_4)
    print(b_tag_keyword_5)
    '''
    #print(x, y, z, a, b)


    #Boolean Operator Pattern
    #   Logic Executed With Tags and Keywords Per Boolean Operator Pattern.  Outcome Must Be True For Rule To Be a Candidate for use.

    if my_concat == "AND":
        if (x and y):
            is_good_rule = "YES"


    elif my_concat == "ANDAND":
        if (x and y and z):
            is_good_rule = "YES"


    elif my_concat == "ANDANDAND":
        if (x and y and z and a):
            is_good_rule = "YES"

    elif my_concat == "ANDANDNOT":
        if ((x and y) and z and (not a)):
            is_good_rule = "YES"

    elif my_concat == "ANDANDANDOR":
        if (x and y and z and (a or b)):
            is_good_rule = "YES"


    elif my_concat == "ANDANDANDAND":
        if (x and y and z and a and b ):
            is_good_rule = "YES"


    elif my_concat == "ANDANDANDNOT":
        if (x and y and z and a and (not b)):
            is_good_rule = "YES"


    elif my_concat == "ANDANDNOTNOT":
        if (x and y and (not a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ANDANDOR":
        if (x and y and (z or a) ):
            is_good_rule = "YES"


    elif my_concat == "ANDANDORAND":
        if (x and y and (z or a) and b ):
            is_good_rule = "YES"


    elif my_concat == "ANDANDORNOT":
        if (x and y and (z or a) and (not b)):
            is_good_rule = "YES"

    elif my_concat == "ANDANDOROR":
        if (x and y and ((z or a) or b)):
            is_good_rule = "YES"


    elif my_concat == "ANDNOT":
        if (x and y and (not z)):
            is_good_rule = "YES"


    elif my_concat == "ANDNOTNOT":
        if (x and y and (not z) and (not a)):
            is_good_rule = "YES"


    elif my_concat == "ANDNOTNOTNOT":
        if (x and y and (not z) and (not a) and (not b)):
            is_good_rule = "YES"


    elif my_concat == "ANDOR":
        if (x and (y or z) ):
            is_good_rule = "YES"


    elif my_concat == "ANDORAND":
         if (x and (y or z) and a ):
            is_good_rule = "YES"


    elif my_concat == "ANDORANDAND":
         if (x and (y or z) and a and b):
            is_good_rule = "YES"


    elif my_concat == "ANDORNOT":
        if (x and (y or z) and (not a) ):
            is_good_rule = "YES"


    elif my_concat == "ANDORNOTNOT":
        if (x and (y or z) and (not a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ANDOROR":
        if (x and ((y or z) or a ) ):
            is_good_rule = "YES"


    elif my_concat == "ANDORORAND":
        if (x and ( (y or z) or a) and b):
            is_good_rule = "YES"


    elif my_concat == "ANDORORNOT":
        if (x and ((y or z) or a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ANDORANDAND":
        if (x and (y or z) and a and b ):
            is_good_rule = "YES"


    elif my_concat == "ANDORANDNOT":
        if (x and (y or z) and a and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ANDORANDOR":
        if (x and (y or z) and (a or b) ):
            is_good_rule = "YES"


    elif my_concat == "ANDOROROR":
        if (x and (((y or z) or a) or b) ):
            is_good_rule = "YES"


    elif my_concat == "NOTNOTNOTNOT":
        if ( x and (not y) and (not z) and (not a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "NOTNOTNOT":
        if ( x and (not y) and (not z) and (not a)):
            is_good_rule = "YES"

    elif my_concat == "NOTNOT":
        if ( x and (not y) and (not z)):
            is_good_rule = "YES"


    elif my_concat == "NOT":
        if ( x and (not y)):
            is_good_rule = "YES"

    elif my_concat == "OR":
        if (x or y ):
            is_good_rule = "YES"


    elif my_concat == "ORAND":
        if ((x or y) and z ):
            is_good_rule = "YES"


    elif my_concat == "ORANDAND":
        if ((x or y) and z and a ):
            is_good_rule = "YES"


    elif my_concat == "ORANDANDAND":
        if ((x or y) and z and a and b ):
            is_good_rule = "YES"


    elif my_concat == "ORANDANDNOT":
        if ((x or y) and z and a and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ORANDANDOR":
        if ((x or y) and z and (a or b) ):
            is_good_rule = "YES"


    elif my_concat == "ORANDNOT":
        if ((x or y) and z and (not a) ):
            is_good_rule = "YES"


    elif my_concat == "ORANDNOTNOT":
        if ((x or y) and z and (not a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ORANDOR":
        if ( (x or y) and (z or a)):
            is_good_rule = "YES"


    elif my_concat == "ORANDORAND":
        if ((x or y) and (z or a) and b ):
            is_good_rule = "YES"


    elif my_concat == "ORANDORNOT":
        if ((x or y) and (z or a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ORANDOROR":
        if ((x or y) and (z or a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "ORNOT":
        if ((x or y) and (not z) ):
            is_good_rule = "YES"


    elif my_concat == "ORNOTNOT":
        if ((x or y) and (not z) and (not a) ):
            is_good_rule = "YES"


    elif my_concat == "ORNOTNOTNOT":
        if ((x or y) and (not z) and (not a) and (not b)):
            is_good_rule = "YES"


    elif my_concat == "OROR":
        if ((x or y) or z ):
            is_good_rule = "YES"


    elif my_concat == "ORORAND":
        if ( ((x or y) or z) and a ):
            is_good_rule = "YES"


    elif my_concat == "ORORANDAND":
        if (((x or y) or z) and a and b ):
            is_good_rule = "YES"


    elif my_concat == "ORORANDNOT":
        if (((x or y) or z) and a and (not b) ):
            is_good_rule = "YES"

    elif my_concat == "ORORANDOR":
        if (((x or y) or z) and (a or b) ):
            is_good_rule = "YES"

    elif my_concat == "ORORNOT":
        if (((x or y) or z) and (not a) ):
            is_good_rule = "YES"


    elif my_concat == "ORORNOTNOT":
        if (((x or y) or z) and (not a) and (not b) ):
            is_good_rule = "YES"


    elif my_concat == "OROROR":
        if ( ((x or y) or z) or a):
            is_good_rule = "YES"


    elif my_concat == "ORORORAND":
        if ((((x or y) or z) or a) and b ):
            is_good_rule = "YES"


    elif my_concat == "ORORORNOT":
        if ( (((x or y) or z) or a) and (not b)):
            is_good_rule = "YES"


    elif my_concat == "OROROROR":
        if ( (((x or y) or z) or a) or b):
            is_good_rule = "YES"

    elif (x and (not y) and (not z) and (not a) and (not b)) and (len(my_concat) < 2) :
        #Meaning that ONLY tag_keyword_1 is not blank, there IS a matching Tag, and NO operators.
        is_good_rule = "YES"
    else:
        pass


    #------------------------------------------------------------------------------------------------------------------------------------
def Search_my_search_list_of_tag_rows(keyword):

    # utf-8 string vs. ordinary byte string
    #both become ordinary byte strings without any escape characters, although may be like: \x3a\x4z etc.
    #for this to work properly, Tags from Calibre metadata.db MUST have been converted to lower case
    #still in utf8 using my SQLite user function to update table _dg_books_tagnames.  Otherwise,
    #comparing lowercase to uppercase words will fail when the original SQLite mysql updated
    #table _dg_books_tagrules based on Tag == Keyword. At this point, converting the Tag to lower case
    #is too late because the Tag Rule won't ever be here to be matched.

    global my_search_list_of_tag_rows  #pure utf8
    global varxyzab
    global s_anythingelse   #"ANYTHING_ELSE"

    varxyzab = False

    my_string_list = []
    del my_string_list
    my_string_list = []

    for row in my_search_list_of_tag_rows:  #All Tags for Current Book
        utf8_to_convert = Strip_UTF8_To_String(row) #does NOT remove spaces or commas
        utf8_to_convert = Strip_Escape_Characters_From_Strings(utf8_to_convert)
        try: #on general principles, but see note above...
            utf8_to_convert = utf8_to_convert.lower()
            utf8_to_convert = utf8_to_convert.replace(" ", mynothing)
        except:
            utf8_to_convert = utf8_to_convert.replace(" ", mynothing)
        my_string_list.append(utf8_to_convert)
        #                                                                                                                                                                     print("a tag for book: ", utf8_to_convert)
    #END FOR

    utf8_to_convert = Strip_UTF8_To_String(keyword)  #does NOT remove spaces or commas
    utf8_to_convert = Strip_Escape_Characters_From_Strings(utf8_to_convert)
    keyword = utf8_to_convert
    keyword = keyword.lower() #already converted to lower case, but do it again on general principles
    keyword = keyword.replace(" ", mynothing)   #Current Keyword being matched...

    #search first for the keyword as a substring of the tag, and then for the tag as a substring of the keyword.   only have what sql provided, though.
    for item in my_string_list:   #this is an ordinary byte string version of the original utf8 list
        #                                                                                                                                                                       print("item: ", item, " keyword: ", keyword)
        n = item.find(keyword)  #e.g. is there a Keyword "Histórico" contained within the Tag "Ficción:Histórico"?  If so, varxyab = True
        g = keyword.find(item)  #e.g. is there a Tag "Ficción:Histórico" contained within the Keyword "Histórico"?    If so, varxyab = True
        if  n >= 0 or g >= 0:
            varxyzab = True
        else:
            if item == keyword:
                varxyzab = True
            else:
                pass
    #END FOR
    del my_string_list

    return varxyzab

    #------------------------------------------------------------------------------------------------------------------------------------
def Compare_Wildcards_To_Tags(varxyzab):
    # The asterisk in the Tag Rules file was changed to a value of ANYTHING_ELSE
    # The boolean operator for each asterisk is required to be NOT (or the language equivalent)
    # Once the asterisk is encountered, then all operators to its right become NOT, and all keywords become ANYTHING_ELSE
    # So, the purpose of this function is to determine if ONLY the Tags equal to the Keywords to the LEFT of the asterisk exist
    # If there are a lot of tags, but only some are equal to the Keywords to the LEFT of the wildcard asterisk, then the Rule is FALSE
    # If the rule is determined to be FALSE, then the boolean values of x, y, z, a, b will be set to FALSE, so the rule will fail
    #     in the boolean equation, and thus be viewed as IS_GOOD_RULE = FALSE.

    #called as:  passed_wildcard_comparison = Compare_Wildcards_To_Tags(varxyzab)
    #so return a True if the rule passed this test, otherwise return a False.

    #Remember that operator for the asterisk wildcard is always NOT.  So, it means "AND NOTHING ELSE EXISTS AS A TAG"
    #     except for the Keywords to the LEFT of the first asterisk wildcard.

    #example Tag Rule:   kw1                            kw2                                                       kw3                                            kw4                                   kw5
    #"Fiction:Fantasy","fantasy","NOT","ANYTHING_ELSE","NOT","ANYTHING_ELSE","NOT","ANYTHING_ELSE","NOT","ANYTHING_ELSE"

    global x_tag_keyword_1  #stripped keyword at this point; byte string only
    global y_tag_keyword_2  #stripped keyword at this point; byte string only
    global z_tag_keyword_3  #stripped keyword at this point; byte string only
    global a_tag_keyword_4  #stripped keyword at this point; byte string only
    global b_tag_keyword_5  #stripped keyword at this point; byte string only

    global my_search_list_of_tag_rows             #raw utf-8 directly via sqlite from metadata.db

    global s_anythingelse                                 #"ANYTHING_ELSE" == wildcard of "*" in Tag Rules after import from csv file

    global my_current_book_id


    varxyzab = False

    my_string_list = []

    for item in my_search_list_of_tag_rows:
        utf8_to_convert = Strip_UTF8_To_String(item) #does NOT remove spaces or commas
        utf8_to_convert = Strip_Escape_Characters_From_Strings(utf8_to_convert)
        try:
            utf8_to_convert = utf8_to_convert.lower()
        except:
            pass
        utf8_to_convert = utf8_to_convert.replace(" ", mynothing)
        utf8_to_convert = utf8_to_convert.replace(",", mynothing)
        n = utf8_to_convert.find("NONE")
        if utf8_to_convert <> "NONE" and n < 0:
            my_string_list.append(utf8_to_convert)

    found_anything_else = False
    found_wildcard = False

    to_the_left_keywords_list = []
    to_the_left_keywords_list.append(x_tag_keyword_1)  #asterisk cannot be in x_tag_keyword_1.  not ever.
    n = y_tag_keyword_2.find(s_anythingelse)
    if y_tag_keyword_2 <> s_anythingelse and n < 0:
        to_the_left_keywords_list.append(y_tag_keyword_2)
        n = z_tag_keyword_3.find(s_anythingelse)
        if z_tag_keyword_3 <> s_anythingelse and n < 0:
            to_the_left_keywords_list.append(y_tag_keyword_2)
            n = a_tag_keyword_4.find(s_anythingelse)
            if a_tag_keyword_4 <> s_anythingelse and n < 0:
                to_the_left_keywords_list.append(a_tag_keyword_4)
                n = b_tag_keyword_5.find(s_anythingelse)
                if b_tag_keyword_5 <> s_anythingelse and n < 0:
                    to_the_left_keywords_list.append(b_tag_keyword_5)
                else:
                    found_wildcard = True
            else:
                found_wildcard = True
        else:
            found_wildcard = True
    else:
        found_wildcard = True

    somebody_found_it= False

    if not found_wildcard:  #no asterisk wildcard exists in this rule, so passes the test by default
        varxyzab = True
        return varxyzab
    else:  # asterisk wildcard exists in this rule
        to_the_left_keywords_list = Remove_List_Duplicates(to_the_left_keywords_list, log)
        my_string_list = Remove_List_Duplicates(my_string_list, log)
        for row in my_string_list:  #created just above
            if found_anything_else:
                break
            somebody_found_it = False
            tag = str(row)  #tag
            for item in to_the_left_keywords_list:   #this is an ordinary string version of the original utf8 list of Tags
                keyword = str(item) #keyword
                n = keyword.find(tag)  #e.g. is there an item Tag  found in the row Left Keyword List?
                if  (n >= 0 or tag == keyword):
                    somebody_found_it = True
            #END FOR
            if somebody_found_it: #means  that all of the keywords were compared to the tag, and there was a tag match on a keyword
                pass
            else:
                #means that the current row tag was not matched to ANY of the item keywords.  Fails the wildcard test.
                found_anything_else = True  #fails the wildcard test
                break
        #END FOR

    del my_string_list

    if found_anything_else: #did find something else, so rule must fail.  Bad Rule.
        varxyzab = False
        return varxyzab
    else: #no Tags other than those in the keywords to the left of the asterisk wildcard were found in the list of Tags; Good Rule.
        varxyzab = True
        return varxyzab

    #------------------------------------------------------------------------------------------------------------------------------------
def Strip_Escape_Characters_From_Strings(s):
    #prior to comparing keywords to tags, strip the escape characters from both

    global mynothing

    s = str(s) #example:  "n\xe3o-fic\xe7\xe3o"  ==  não-ficção in utf8

    s = s.replace("\\", mynothing, 8)    #now "nxe3o-ficxe7xe3o"

    return s

    #------------------------------------------------------------------------------------------------------------------------------------

def Search_Table_dg_genre_author_rules(my_db, my_cursor, my_current_book_id, notifications, log):

    global mynothing
    global tmp_fiction_genre     #still in utf8
    global tmp_factual_genre    #still in utf8

    my_temp_record = []

    tmp_fiction_genre = "NONE"
    tmp_factual_genre = "NONE"

    sleep(.001)  #to avoid db busy/locked error when python is running faster than sqlite

    my_temps = []
    del my_temps
    my_temps = []

    try:
        mysql = "SELECT fiction_genre, factual_genre FROM _dg_genre_author_rules \
                        WHERE author IN(SELECT name FROM __book_author_name_sort WHERE book = '" + my_current_book_id + "') ;"
        my_cursor.execute (mysql)
        my_temps = my_cursor.fetchall()
        if my_temps:
            x = len(my_temps)
            if x > 0:
                for row in my_temps:
                    s0, s1 = row    #still in utf8
                    tmp_fiction_genre = s0   #  Fiction:Science       #still in utf8
                    tmp_factual_genre = s1   #  Factual:Science      #still in utf8
                    break     #if duplicate authors were created in the _dg_author_rules table, only the first found [0] will be considered
            else:
                return
        else:
            return
    except Exception as e:
        log(str(e))
        log("Author Rule Selection Error.")

    #----------------------------------------------------------------------------------------------------------
def Clean_Strings_Space_Not_Comma(tmp_string):

    global mynothing

    tmp_string = tmp_string.replace(' ', mynothing, 20)

    return tmp_string

    #------------------------------------------------------------------------------------------------------------------------------------

def Clean_Strings_Comma_Not_Space(tmp_string):

    global mynothing

    tmp_string = tmp_string.replace(",", mynothing, 16)

    return tmp_string

   #------------------------------------------------------------------------------------------------------------------------------------

def Clean_Space_Comma(tmp_string):

    global mynothing

    tmp_string = tmp_string.replace(" ", mynothing, 40)
    tmp_string = tmp_string.replace(",", mynothing, 40)

    return tmp_string

   #---------------------------------------------------------------------------------------------------

    #---------------------------------------------------------------------------------------------------
def Remove_List_Duplicates(a_list, log):

    #do not sort!

    s_set = set(a_list)

    b_list = []
    for item in a_list:
        try:
            b_list.append(item)
        except Exception as e:
            s = "Remove_List_Duplicates item append exception, but was ignored without consequences...."
            log(s)
            s = str(e)
            log(s)


    return b_list
   #---------------------------------------------------------------------------------------------------------------------------------------
def Strip_UTF8_To_String(u_string):

    #does NOT remove commas and/or spaces here; do it separately if needed, but do NOT do it here...

    global mynothing

    utf8_to_convert = u_string

    try:
         utf8_to_convert.decode('utf8').encode('iso8859-15', "strict")  #<type 'unicode'> to <type 'str'>
    except:
        try:
            utf8_to_convert.encode('iso8859-15', "strict")
        except:
            try:
                utf8_to_convert.encode('ascii', "replace")  #<type 'unicode'> to <type 'str'
            except:
                try:
                    utf8_to_convert = str(utf8_to_convert)
                    utf8_to_convert = utf8_to_convert.replace("u'", mynothing, 100)
                    utf8_to_convert = utf8_to_convert.replace("'", mynothing, 100)
                    utf8_to_convert = utf8_to_convert.replace("(", mynothing, 100)
                    utf8_to_convert = utf8_to_convert.replace(")", mynothing, 100)
                    try:
                        log("unicode conversion to byte string was problematic:  ", str(utf8_to_convert))
                    except:
                        pass
                except:
                    pass

    try: #backup logic
        utf8_to_convert = utf8_to_convert.replace("u'", mynothing, 100)
        utf8_to_convert = utf8_to_convert.replace("'", mynothing, 100)
        utf8_to_convert = utf8_to_convert.replace("(", mynothing, 100)
        utf8_to_convert =utf8_to_convert.replace(")", mynothing, 100)
        try:
            log("unicode conversion to byte string was problematic:  ", str(utf8_to_convert))
        except:
            pass
    except:
        pass

    return utf8_to_convert

    #---------------------------------------------------------------------------------------------------
def Create_SQLite_User_Function(my_db, my_cursor, log):
        #native SQLite cannot compare Unicode strings without first
        #   decoding them to ASCII.  This fixes that deficiency so
        #   Tags can be all lowercase when compared to Tag Rule Keywords.
        #see https://docs.python.org/2/library/sqlite3.html

        global my_terminate_early

        #paramers are: function name for SQLite; number of parameters; Python callable function
        try:
            #this is apsw:
            my_db.createscalarfunction("make_utf8_lowercase", SQLite_User_Function_1)
            #this is sqlite
            # my_db.create_function("make_utf8_lowercase", 1, SQLite_User_Function_1)
        except:
            my_terminate_early = True
            log("Create_SQLite_User_Function 1 failed...cannot proceed...")

       #paramers are: function name for SQLite; number of parameters; Python callable function
        try:
            #this is apsw:
            my_db.createscalarfunction("update_utf8_for_display", SQLite_User_Function_2)
        except:
            my_terminate_early = True
            log("Create_SQLite_User_Function 2 failed...cannot proceed...")


    #---------------------------------------------------------------------------------------------------
def SQLite_User_Function_1(s):
    #makes Unicode utf-8 strings lowercase for proper matching
    #how to use in SQLite, bearing in mind that this is a "simple user function" not
    #an "aggregate user function" that would only be usable within a SELECT statement:
    #------------------------------------------------------------------------------------------------------------
    #mysql = "UPDATE _dg_books_tagnames SET name = (make_utf8_lowercase(name) );"
    #------------------------------------------------------------------------------------------------------------

    t = s
    if t is None: #ignore Nulls being passed by SQLite
        return s
    else:
        try:
            if isinstance(t, unicode):
                t = t.lower()
                t = t.replace(" ", "", 10)
                return t
            else:
                pass
        except:
            #print("SQLite_User_Function_1 Error: t = t.lower() Failed.")
            pass

    return s
   #-----------------------------------------------------------------------------------------------------------------
def SQLite_User_Function_2(s):
    #------------------------------------------------------------------------------------------------------------
    #mysql = "UPDATE custom_column_4 SET value = (update_utf8_for_display(value)  );"
    #------------------------------------------------------------------------------------------------------------

    mynothing = ""

    t = s
    if t is None: #ignore Nulls being passed by SQLite
        return s
    else:
        try:
            if not isinstance(t, unicode):
                t = unicode(t)
            if isinstance(t, unicode):
                t = eval(t)   #example:  unicode such as  u'n\xe3o-fic\xe7\xe3o'   that user wants to see in gui custom column as:  não-ficção
                return t
            else:
                __printsafe("SQLite_User_Function_2...........not unicode:", str(t))
                pass
        except Exception as e:
            #__printsafe(str(e))
            #__printsafe("SQLite_User_Function_2 Error: 2t = eval(t) Failed.")
            pass

    return s

     #--------------------------------------------------------------------------------------------------------------------------------------------
def Accumulate_Missing_Tag_Combinations(my_db, my_cursor, my_current_book_id,log):
    #insert into table for perusal by user

    try:
        my_cursor.execute("begin")  #apsw
        mysql = "INSERT OR REPLACE INTO _dg_missing_tag_rules (id,combination,date_added) SELECT null, tagsconcat,null \
                                FROM  __dg_tags_concatenate WHERE book = '" + my_current_book_id + "'  AND tagsconcat NOT NULL ; "
        my_cursor.execute (mysql)
        my_cursor.execute("commit")
        #log("Tag Combination with no valid Tag Rule was added to table _dg_missing_tag_rules.  Review required.")
    except Exception as e:
        log("failure to insert missing tag combinations in tag rules for book id: " + str(my_current_book_id))
        log(str(e))
        try:
            my_cursor.execute("commit")   #avoid outstanding transaction
        except:
            pass


    #----------------------------------------------------------------------------------------------------------
def Create_DG_Tables_If_Not_Exist(my_db, my_cursor, log):

    mysql = "CREATE TABLE IF NOT EXISTS _dg_genre_tag_rules_fiction (\
                       id INTEGER PRIMARY KEY AUTOINCREMENT,\
                       new_genre TEXT NOT NULL COLLATE NOCASE,\
                       tag_keyword_1 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_1 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_2 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_2 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_3 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_3 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_4 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_4 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_5 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE' ) "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_genre_tag_rules_factual (\
                       id INTEGER PRIMARY KEY AUTOINCREMENT,\
                       new_genre TEXT NOT NULL COLLATE NOCASE,\
                       tag_keyword_1 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_1 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_2 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_2 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_3 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_3 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_4 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_4 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_5 TEXT  NOT NULL COLLATE NOCASE DEFAULT 'NONE' ) "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_genre_author_rules(\
                   id    INTEGER PRIMARY KEY AUTOINCREMENT,\
                   author TEXT NOT NULL COLLATE NOCASE,\
                   fiction_genre TEXT NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                   factual_genre TEXT NOT NULL COLLATE NOCASE DEFAULT 'NONE',\
                   UNIQUE(author)) "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_nf_language_keywords(\
                   id    INTEGER PRIMARY KEY AUTOINCREMENT,\
                   nf_keyword TEXT NOT NULL COLLATE NOCASE,\
                   UNIQUE(nf_keyword)) "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)


    mysql = "CREATE TABLE IF NOT EXISTS _dg_books_factual(\
                  id INTEGER PRIMARY KEY,\
                  book INTEGER NOT NULL,\
                  tag INTEGER NOT NULL,\
                  name TEXT NOT NULL COLLATE NOCASE,\
                  factual TEXT COLLATE NOCASE)"         #MUST be allowed to be null...

    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_books_tagnames(\
                      id INTEGER PRIMARY KEY,\
                      book INTEGER NOT NULL,\
                      tag INTEGER NOT NULL,\
                      name TEXT NOT NULL COLLATE NOCASE)"


    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)


    mysql = "CREATE TABLE IF NOT EXISTS _dg_books_tagrules (\
                       book INTEGER NOT NULL,\
                       type TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       rule_id INTEGER DEFAULT 0,\
                       new_genre TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_1 TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       tag_operator_1 TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_2 TEXT COLLATE NOCASE DEFAULT  'NONE',\
                       tag_operator_2 TEXT COLLATE NOCASE DEFAULT  'NONE',\
                       tag_keyword_3 TEXT COLLATE NOCASE DEFAULT  'NONE',\
                       tag_operator_3 TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       tag_keyword_4 TEXT COLLATE NOCASE DEFAULT  'NONE',\
                       tag_operator_4 TEXT COLLATE NOCASE DEFAULT  'NONE',\
                       tag_keyword_5 TEXT COLLATE NOCASE DEFAULT 'NONE',\
                       PRIMARY KEY (book, type, rule_id, new_genre)  )"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_books(book INTEGER PRIMARY KEY,\
                                             type TEXT COLLATE NOCASE DEFAULT NULL )"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_books_factual_index_1 ON _dg_books_factual(book, tag, name, factual);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_books_index_1 ON _dg_books(book, type);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_books_tagnames_index_1 ON _dg_books_tagnames(book, tag, name);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_books_tagrules_index_1 ON _dg_books_tagrules(book, tag_keyword_1);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_books_type_index_1 ON _dg_books(type);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_genre_tag_rules_factual_index_1 ON _dg_genre_tag_rules_factual(tag_keyword_1);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE INDEX IF NOT EXISTS _dg_genre_tag_rules_fiction_index_1 ON _dg_genre_tag_rules_fiction(tag_keyword_1);"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE VIEW IF NOT EXISTS __dg_match_tags_and_keywords_factual AS SELECT * FROM _dg_books, _dg_genre_tag_rules_factual \
                        WHERE _dg_books.type = 'FACTUAL' \
                        AND _dg_books.book IN (SELECT book FROM _dg_books_factual WHERE book = _dg_books.book) \
                        AND  _dg_genre_tag_rules_factual.tag_keyword_1 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                         OR  _dg_genre_tag_rules_factual.tag_keyword_2 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                         OR  _dg_genre_tag_rules_factual.tag_keyword_3 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                         OR  _dg_genre_tag_rules_factual.tag_keyword_4 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                         OR  _dg_genre_tag_rules_factual.tag_keyword_5 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                        AND _dg_genre_tag_rules_factual.tag_keyword_1 IN (SELECT nf_keyword FROM _dg_nf_language_keywords \
                        WHERE nf_keyword = _dg_genre_tag_rules_factual.tag_keyword_1  ) ; "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)


    mysql = "CREATE VIEW IF NOT EXISTS __dg_match_tags_and_keywords_fiction AS SELECT * FROM _dg_books, _dg_genre_tag_rules_fiction \
                WHERE _dg_books.type = 'FICTION' \
                 AND _dg_books.book NOT IN (SELECT book FROM _dg_books_factual WHERE book = _dg_books.book) \
                AND  _dg_genre_tag_rules_fiction.tag_keyword_1 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                 OR  _dg_genre_tag_rules_fiction.tag_keyword_2 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                 OR  _dg_genre_tag_rules_fiction.tag_keyword_3 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                 OR  _dg_genre_tag_rules_fiction.tag_keyword_4 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                 OR  _dg_genre_tag_rules_fiction.tag_keyword_5 IN (SELECT name  FROM _dg_books_tagnames WHERE book = _dg_books.book) \
                AND _dg_genre_tag_rules_fiction.tag_keyword_1 NOT IN (SELECT nf_keyword FROM _dg_nf_language_keywords  \
                WHERE nf_keyword = _dg_genre_tag_rules_fiction.tag_keyword_1) ;"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE TABLE IF NOT EXISTS _dg_missing_tag_rules (\
                    id INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL , combination TEXT NOT NULL  UNIQUE , \
                    date_added DATETIME NOT NULL  DEFAULT CURRENT_TIMESTAMP ) "
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)

    mysql = "CREATE VIEW IF NOT EXISTS __dg_tags_concatenate AS  SELECT book, group_concat(myconcat,',') AS tagsconcat \
                    FROM (SELECT book,CASE WHEN tagname IS NULL THEN 'unknown'  WHEN tagname = ',' THEN 'unknown' \
                    WHEN tagname = ' ' THEN 'unknown' WHEN tagname = ''  THEN 'unknown'  ELSE tagname END AS myconcat \
                    FROM __tags_by_author_by_book ORDER BY tagname  ) GROUP BY book"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)


    #------------------------------------------------------------------------------------------------------------------------------
def Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log):

    try:
        try:
            my_cursor.execute("begin")  #apsw
        except:
            pass
        my_cursor.execute (mysql)
        my_cursor.execute ("commit")  #apsw
    except Exception as e:
        log("Exception in Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log) ")
        log(str(e))
        log(mysql)
        raise e

   #-----------------------------------------------------------------------------------------------------------------
def __printsafe(*arg):

    try:
        print(arg)
        pass
    except:
        pass
        print("...cannot be printed...")

   #-----------------------------------------------------------------------------------------------------------------
def Update_Custom_Column_Genre(my_db, my_cursor, log):

    global book_new_genre_dict         # book_new_genre_dict is always pure unicode utf8
    global custom_table
    global custom_id
    global books_custom_column_X_link_str

    custom_table = str(custom_table)
    books_custom_column_X_link_str = str(books_custom_column_X_link_str)

    n = len(book_new_genre_dict)
    if n == 0:
        log("No entries in Book/New Genre List")
        return

    # book_new_genre_dict is always pure unicode utf8

    my_cursor.execute("begin")  #apsw
    for book,genre in book_new_genre_dict.iteritems():
        try:
            mysql = str("INSERT OR REPLACE INTO [CUSTOMTABLE] (id,value) VALUES (null, ?)")
            mysql = str(mysql.replace("[CUSTOMTABLE]", str(custom_table), 1))
            if not isinstance(genre, unicode):     #just in case
                genre = unicode(genre)
            my_cursor.execute(mysql, [genre])   #apsw
        except Exception as e:
            log("ERROR in actually updating the #genre custom column value table")
            log(str(e))
            log(str(mysql))
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
        sleep(1.0)
    except:
        pass

    my_cursor.execute("begin")  #apsw
    for book,genre in book_new_genre_dict.iteritems():
        try:
            mysql = str("DELETE FROM [books_custom_column_17_link] WHERE book = ? ")
            mysql = str(mysql.replace("[books_custom_column_17_link]", str(books_custom_column_X_link_str), 1))
            my_cursor.execute(mysql, [book])   #apsw
        except Exception as e:
            log("ERROR in actually updating the #genre custom column - book link table")
            log(str(e))
            log(str(mysql))
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    my_cursor.execute("begin")  #apsw
    for book,genre in book_new_genre_dict.iteritems():
        try:
            mysql = str("INSERT OR REPLACE INTO [books_custom_column_17_link] (id,book,value)  SELECT null,?,id FROM [custom_column_17] WHERE value = ? ")
            mysql = str(mysql.replace("[books_custom_column_17_link]", str(books_custom_column_X_link_str), 1))
            mysql = str(mysql.replace("[custom_column_17]", str(custom_table), 1))
            if not isinstance(genre, unicode):        #just in case
                genre = unicode(genre)
            my_cursor.execute(mysql, [book,genre])   #apsw
            sleep(0.1)
        except Exception as e:
            log("ERROR in actually updating the #genre custom column - book link table")
            log(str(e))
            log(str(mysql))
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    #now eval the value to turn the unicode control characters into what the user wants to see on the gui
    try:
        my_cursor.execute("begin")  #apsw
        mysql = str("UPDATE [CUSTOMTABLE] SET value = (update_utf8_for_display(value)  );")
        mysql = str(mysql.replace("[CUSTOMTABLE]", str(custom_table), 1))
        my_cursor.execute(mysql)
        my_cursor.execute("commit")  #apsw
    except:
            try:
                my_cursor.execute("commit")  #apsw
            except:
                pass

   #-----------------------------------------------------------------------------------------------------------------
def Get_Custom_Table_Name(my_db,my_cursor,log):
    global mynothing

    # Determine what the custom column Genre has as a physical field name
    from calibre_plugins.quarantine_and_scrub.config import prefs
    custom_field = prefs['genre']
    log(" ")
    log("Q&S Configured Custom Column #Name to be used is:  " + str(custom_field))
    log(" ")
    log("-----------------------------------------------------------------------------------------------")
    log("-----------------------------------------------------------------------------------------------")

    custom_field = str(custom_field.replace("#", mynothing, 1))

    global custom_table
    global custom_id
    global books_custom_column_X_link_str

    my_terminate_early = False

    mysql = str("SELECT id FROM custom_columns WHERE label = '[genre]' ")
    mysql = str(mysql.replace("[genre]", str(custom_field)))
    my_cursor.execute (mysql)
    rows = my_cursor.fetchall()
    for row in rows:
        for col in row:
            custom_id = str(col)
            custom_id_str = str(custom_id)

    s = str(custom_table)
    custom_id_str = str(custom_id)
    custom_table = str(s.replace('X', custom_id_str, 1))
    s = str(books_custom_column_X_link_str)
    books_custom_column_X_link_str = str(s.replace('X', custom_id_str, 1))

    if str(custom_table) == str("custom_column_999") or str(custom_table) == str("custom_column_X") \
        or str(books_custom_column_X_link_str) == str("books_custom_column_X_link"):
        log("No Custom Table Column genre Configured By User Yet.")
        log("Derive Genres terminated. Add genre as a custom column.    ")
        my_terminate_early = True

    return my_terminate_early

   #-----------------------------------------------------------------------------------------------------------------
def Validate_User_Maintained_Rules_Tables(my_db,my_cursor,log):

    global mynothing

    mysql = str("\
            BEGIN TRANSACTION;\
            DELETE FROM _dg_genre_tag_rules_factual WHERE tag_keyword_1 NOT IN(SELECT nf_keyword FROM _dg_nf_language_keywords);\
            COMMIT; ")
    my_cursor.execute(mysql)

    mysql = str("\
            BEGIN TRANSACTION;\
            DELETE FROM _dg_genre_tag_rules_fiction WHERE tag_keyword_1 IN(SELECT nf_keyword FROM _dg_nf_language_keywords);\
            COMMIT; ")
    my_cursor.execute(mysql)


    my_rules_sql = []

    #factual------------------
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_keyword_2 = '*' WHERE tag_keyword_2 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_keyword_3 = '*' WHERE tag_keyword_3 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_keyword_4 = '*' WHERE tag_keyword_4 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_keyword_5 = '*' WHERE tag_keyword_5 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)

    #fiction------------------
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_keyword_2 = '*' WHERE tag_keyword_2 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_keyword_3 = '*' WHERE tag_keyword_3 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_keyword_4 = '*' WHERE tag_keyword_4 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_keyword_5 = '*' WHERE tag_keyword_5 LIKE '%ANYTHING_ELSE%' ")
    my_rules_sql.append(mysql)

    #factual------------------
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_1 = 'OR' WHERE tag_operator_1 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_2 = 'OR' WHERE tag_operator_2 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_3 = 'OR' WHERE tag_operator_3 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_4 = 'OR' WHERE tag_operator_4 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)

    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_1 = 'AND' WHERE tag_operator_1 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_2 = 'AND' WHERE tag_operator_2 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_3 = 'AND' WHERE tag_operator_3 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_4 = 'AND' WHERE tag_operator_4 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)


    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_1 = 'NOT' WHERE tag_operator_1 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_2 = 'NOT' WHERE tag_operator_2 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_3 = 'NOT' WHERE tag_operator_3 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_4 = 'NOT' WHERE tag_operator_4 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)

    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_1 = 'NONE' WHERE tag_operator_1 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_2 = 'NONE' WHERE tag_operator_2 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_3 = 'NONE' WHERE tag_operator_3 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET tag_operator_4 = 'NONE' WHERE tag_operator_4 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)

    #fiction------------------
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_1 = 'OR' WHERE tag_operator_1 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_2 = 'OR' WHERE tag_operator_2 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_3 = 'OR' WHERE tag_operator_3 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_4 = 'OR' WHERE tag_operator_4 = 'or' OR tag_operator_1 = 'Or' ")
    my_rules_sql.append(mysql)

    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_1 = 'AND' WHERE tag_operator_1 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_2 = 'AND' WHERE tag_operator_2 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_3 = 'AND' WHERE tag_operator_3 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_4 = 'AND' WHERE tag_operator_4 = 'and' OR tag_operator_1 = 'And' ")
    my_rules_sql.append(mysql)

    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_1 = 'NOT' WHERE tag_operator_1 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_2 = 'NOT' WHERE tag_operator_2 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_3 = 'NOT' WHERE tag_operator_3 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_4 = 'NOT' WHERE tag_operator_4 = 'not' OR tag_operator_1 = 'Not' ")
    my_rules_sql.append(mysql)

    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_1 = 'NONE' WHERE tag_operator_1 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_2 = 'NONE' WHERE tag_operator_2 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_3 = 'NONE' WHERE tag_operator_3 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET tag_operator_4 = 'NONE' WHERE tag_operator_4 = 'none' OR tag_operator_1 = 'None' ")
    my_rules_sql.append(mysql)

    #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #fiction------------------
    mysql = "DELETE FROM  _dg_genre_tag_rules_fiction WHERE tag_keyword_1 = '*' "
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET \
                            tag_operator_1 = 'NOT' ,\
                            tag_operator_2 = 'NONE',\
                            tag_operator_3 = 'NONE',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_3 = 'NONE',\
                            tag_keyword_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_2 = '*' ")
    my_rules_sql.append(mysql)
    #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #fiction------------------
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET \
                            tag_operator_2 = 'NOT',\
                            tag_operator_3 = 'NONE',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_3 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #fiction------------------

    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET \
                            tag_operator_3 = 'NOT',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_4 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #fiction------------------


    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET \
                            tag_operator_4 = 'NOT' \
                        WHERE tag_keyword_5 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []






  #factual------------------
    mysql = "DELETE FROM  _dg_genre_tag_rules_factual WHERE tag_keyword_1 = '*' "
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET \
                            tag_operator_1 = 'NOT' ,\
                            tag_operator_2 = 'NONE',\
                            tag_operator_3 = 'NONE',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_3 = 'NONE',\
                            tag_keyword_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_2 = '*' ")
    my_rules_sql.append(mysql)
    #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #factual------------------
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET \
                            tag_operator_2 = 'NOT',\
                            tag_operator_3 = 'NONE',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_3 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #factual------------------

    mysql = str("UPDATE _dg_genre_tag_rules_factual SET \
                            tag_operator_3 = 'NOT',\
                            tag_operator_4 = 'NONE',\
                            tag_keyword_5 = 'NONE' \
                        WHERE tag_keyword_4 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #factual------------------


    mysql = str("UPDATE _dg_genre_tag_rules_factual SET \
                            tag_operator_4 = 'NOT' \
                        WHERE tag_keyword_5 = '*' ")
    my_rules_sql.append(mysql)
   #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []



    #factual------------------
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_1 <> 'NONE' AND tag_operator_1 <> 'OR' AND \
                        tag_operator_1 <> 'AND' AND tag_operator_1 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_2 <> 'NONE' AND tag_operator_2 <> 'OR' AND \
                        tag_operator_2 <> 'AND' AND tag_operator_2 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_3 <> 'NONE' AND tag_operator_3 <> 'OR' AND \
                        tag_operator_3 <> 'AND' AND tag_operator_3 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_factual SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                    (tag_operator_4 <> 'NONE' AND tag_operator_4 <> 'OR' AND \
                    tag_operator_4 <> 'AND' AND tag_operator_4 <> 'NOT' )")
    my_rules_sql.append(mysql)

    #fiction------------------
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_1 <> 'NONE' AND tag_operator_1 <> 'OR' AND \
                        tag_operator_1 <> 'AND' AND tag_operator_1 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_2 <> 'NONE' AND tag_operator_2 <> 'OR' AND \
                        tag_operator_2 <> 'AND' AND tag_operator_2 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                        (tag_operator_3 <> 'NONE' AND tag_operator_3 <> 'OR' AND \
                        tag_operator_3 <> 'AND' AND tag_operator_3 <> 'NOT' )")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_tag_rules_fiction SET new_genre = 'TAG OPERATOR ERROR' WHERE \
                    (tag_operator_4 <> 'NONE' AND tag_operator_4 <> 'OR' AND \
                    tag_operator_4 <> 'AND' AND tag_operator_4 <> 'NOT' )")
    my_rules_sql.append(mysql)


    #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        my_cursor.execute(mysql)
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

    del my_rules_sql
    my_rules_sql = []

    #to be added...


    #---------------------------
    #author rules -------------
    #cannot do simply with sqlite user function due to table constraints re: uppercase vs. lowercase
    Make_Author_Names_Lowercase(my_db,my_cursor,log)
    #---------------------------

   #-----------------------------------------------------------------------------------------------------------------
def Seed_User_Maintained_Rules_Tables(my_db,my_cursor,log):



    mysql = "SELECT Count(*) FROM _dg_genre_tag_rules_fiction"
    my_cursor.execute(mysql)
    count1 = my_cursor.fetchall()
    for row in count1:
        for col in row:
            count1 = col
    count1 = str(Strip_UTF8_To_String(count1))     # 0
    if count1 <> "0":
        return
    else:
        log("Seed rows will be added to the DG rules tables because they are empty.")

    mysql = str("\
            BEGIN TRANSACTION;\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(56,'factual');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(57,'noficció');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(58,'noficción');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(59,'sachbüch');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(60,'não-ficção');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(61,'tényleges');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(62,'staðreyndir');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(63,'fíorasach');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(64,'gerçek');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(65,'dejanska');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(66,'factuel');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(67,'fakta');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(68,'faktaj');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(69,'faktik');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(70,'faktiki');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(71,'faktiline');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(72,'faktinis');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(73,'faktisks');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(74,'faktual');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(75,'faktuelle');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(76,'faktyczny');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(77,'faptic');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(78,'fatti');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(79,'fattwali');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(80,'fatual');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(81,'feitelijk');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(82,'feitelike');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(83,'ffeithiol');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(84,'kuyiqiniso');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(85,'non-fictie');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(86,'nonfiction');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(87,'non-fiction');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(88,'non-fictive');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(89,'non-fiktion');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(90,'nyata');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(91,'reale');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(92,'rerum');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(93,'saca');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(94,'sachlich');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(95,'sahihi');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(96,'saklig');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(97,'tinuod');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(98,'tosiasiallinen');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(99,'tseeb');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(100,'verdad');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(101,'verdade');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(102,'veritable');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(103,'vero');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(104,'vrai');\
            INSERT OR IGNORE INTO _dg_nf_language_keywords VALUES(105,'wahr');\
            COMMIT; ")
    my_cursor.execute(mysql)
    log("Seed Rows Added to Table _dg_nf_language_keywords")

    mysql = str("\
                BEGIN TRANSACTION;\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(223,'Ficcion:Ciencia','ciencia','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(224,'Ficcion:Ciencia','ficcion:ciencia','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(225,'Ficción:Ciencia','ciencia','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(226,'Ficción:Ciencia','ficción:ciencia','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(227,'Ficción:Ciencia-Novela','ficción:ciencia','AND','novela','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(228,'Ficción:Ciencia-Novela','ficción:ciencia-novela','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(229,'Ficción:Histórico','ficción:histórico','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(230,'Ficción:Histórico','histórico','AND','español','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(231,'Ficción:Intriga-Policíaco','ficción:intriga-policíaco','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(232,'Ficción:Intriga-Policíaco','intriga','AND','policíaco','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(233,'Fiction:Action&Adventure','action','OR','adventure','OR','thriller','OR','suspense','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(234,'Fiction:Action&Adventure','fiction:action&adventure','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(235,'Fiction:Action&Adventure','action','OR','adventue','NOT','*','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(236,'Fiction:Anthology','anthology','OR','anthologies','OR','collection','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(237,'Fiction:Anthology','fiction:anthology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(238,'Fiction:Autobiographical&Biographical','autobiographical','OR','biographical','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(239,'Fiction:Autobiographical&Biographical','fiction:autobiographical&biographical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(240,'Fiction:Children','children','NOT','juvenile','NOT','youth','NOT','ya','NOT','teenager');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(241,'Fiction:Children','fiction:children','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(242,'Fiction:Classics','classics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(243,'Fiction:Classics','fiction:classics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(244,'Fiction:Comics&GraphicNovels','comics','OR','graphicnovels','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(245,'Fiction:Comics&GraphicNovels','fiction:comics&graphicnovels','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(246,'Fiction:Cowboys','cowboy','OR','cowboys','OR','westerns','OR','western','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(247,'Fiction:Dystopian&Apocalyptic','dystopian','OR','apocalyptic','OR','dystopia','OR','apocalypse','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(248,'Fiction:Dystopian&Apocalyptic','fiction:dystopian&apocalyptic','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(249,'Fiction:Espionage','espionage','NOT','war','NOT','NONE','NOT','NONE','NOT','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(250,'Fiction:Espionage','fiction:espionage','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(251,'Fiction:Fantasy','fantasy','NOT','paranormal','NOT','steampunk','NOT','urban','NOT','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(252,'Fiction:Fantasy','fiction:fantasy','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(253,'Fiction:Fantasy-Paranormal','fantasy','AND','paranormal','AND','supernatural','AND','horror','AND','vampire');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(254,'Fiction:Fantasy-Paranormal','fiction:fantasy-paranormal','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(255,'Fiction:Fantasy-Romance','fantasy','AND','romance','AND','paranormal','AND','urban','AND','steampunk');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(256,'Fiction:Fantasy-Romance','fiction:fantasy-romance','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(257,'Fiction:Fantasy-Steampunk','fiction:fantasy-steampunk','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(258,'Fiction:Fantasy-Steampunk','steampunk','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(259,'Fiction:Fantasy-Urban','fantasy','AND','urban','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(260,'Fiction:Fantasy-Urban','fiction:fantasy-urban','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(261,'Fiction:Folk Tales','fiction:folktales','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(262,'Fiction:Folk Tales','folktales','OR','folkstories','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(263,'Fiction:General','default','NOT','*','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(264,'Fiction:General','fiction','NOT','*','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(265,'Ficcion:Novelas','español','AND','novela','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(266,'Fiction:Historical','fiction:historical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(267,'Fiction:Historical','historical','OR','history','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(268,'Fiction:Horror','fiction:horror','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(269,'Fiction:Horror','horror','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(270,'Fiction:Humor','fiction:humor','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(271,'Fiction:Humor','humor','OR','humour','OR','comedy','OR','funny','OR','amusing');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(272,'Fiction:Intrigue','fiction:intrigue','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(273,'Fiction:Intrigue','intrigue','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(274,'Fiction:Jewish','fiction:jewish','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(275,'Fiction:Jewish','jewish','OR','judaism','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(276,'Fiction:Legal','fiction:legal','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(277,'Fiction:Legal','legal','OR','lawyer','OR','attorney','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(278,'Fiction:Legends&Myths&Fables','fiction:legends&myths&fables','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(279,'Fiction:Legends&Myths&Fables','legends','OR','myths','OR','fables','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(280,'Fiction:Literary','fiction:literary','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(281,'Fiction:Literary','literary','OR','literature','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(282,'Fiction:Mafia','fiction:mafia','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(283,'Fiction:Mafia','mafia','OR','mafioso','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(284,'Fiction:Medical','fiction:medical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(285,'Fiction:Medical','medical','OR','medicine','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(286,'Fiction:Mysteries&Detectives','fiction:mysteries&detectives','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(287,'Fiction:Mysteries&Detectives','mysteries','AND','detectives','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(288,'Fiction:Mystery','fiction:mystery','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(289,'Fiction:Mystery','mystery','OR','mysteries','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(290,'Fiction:Philosophy','fiction:philosophy','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(291,'Fiction:Philosophy','philosophy','OR','philosophical','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(292,'Fiction:Political','fiction:political','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(293,'Fiction:Political','political','OR','politics','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(294,'Fiction:Psychological','fiction:psychological','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(295,'Fiction:Psychological','psychological','OR','psychology','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(296,'Fiction:Religious','fiction:religious','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(297,'Fiction:Religious','religious','OR','religion','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(298,'Fiction:Romance','fiction:romance','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(299,'Fiction:Romance','romance','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(300,'Fiction:Romance-Adult','fiction:romance-adult','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(301,'Fiction:Romance-Adult','romance','AND','adult','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(302,'Fiction:Romance-Historical','fiction:romance-historical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(303,'Fiction:Romance-Historical','romance','AND','historical','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(304,'Fiction:Romance-Interracial','fiction:romance-interracial','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(305,'Fiction:Romance-Interracial','interracialromance','OR','interracial','OR','romance','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(306,'Fiction:Romance-Paranormal','fiction:romance-paranormal','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(307,'Fiction:Romance-Paranormal','romance','AND','paranormal','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(308,'Fiction:Romance-Suspense','fiction:romance-suspense','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(309,'Fiction:Romance-Suspense','romance','AND','suspense','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(310,'Fiction:Satire','fiction:satire','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(311,'Fiction:Satire','satire','OR','satirical','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(312,'Fiction:Science','fiction:science','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(313,'Fiction:Science','science','OR','wissenschaft','OR','ciencia','OR','scienza','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(314,'Fiction:Science-SpaceOpera','fiction:science-spaceopera','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(315,'Fiction:Science-SpaceOpera','science','AND','space','AND','opera','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(316,'Fiction:Science-Steampunk','fiction:science-steampunk','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(317,'Fiction:Science-Steampunk','science','AND','steampunk','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(318,'Fiction:Science&Fantasy','fiction:science&fantasy','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(319,'Fiction:Science&Fantasy','science','AND','fantasy','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(320,'Fiction:Shapeshifters','fiction:shapeshifters','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(321,'Fiction:Shapeshifters','fiction:shapeshifters','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(322,'Fiction:Shapeshifters','fiction:shapeshifters','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(323,'Fiction:Shapeshifters','shapeshifters','OR','shapeshifter','OR','werewolves','OR','werewolf','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(324,'Fiction:Shapeshifters','werecat','OR','werepanther','OR','werewolves','OR','werewolf','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(325,'Fiction:Shapeshifters','werepig','OR','weregoat','OR','werewolves','OR','werewolf','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(326,'Fiction:Short-Stories','fiction:short-stories','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(327,'Fiction:Short-Stories','short','OR','short-stories','OR','anthology','OR','anthologies','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(328,'Fiction:Supernatural','fiction:supernatural','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(329,'Fiction:Supernatural','supernatural','OR','ghosts','OR','spirits','OR','horror','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(330,'Fiction:Suspense&Thriller','fiction:suspense&thriller','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(331,'Fiction:Suspense&Thriller','suspense','OR','thriller','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(332,'Fiction:Urban','fiction:urban','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(333,'Fiction:Urban','urban','NOT','fantasy','NOT','NONE','NOT','NONE','NOT','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(334,'Fiction:Vampires','fiction:vampires','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(335,'Fiction:Vampires','vampires','OR','vampire','OR','vampyre','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(336,'Fiction:War&Espionage','fiction:war&espionage','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(337,'Fiction:War&Espionage','war','AND','espionage','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(338,'Fiction:Werewolves','fiction:werewolves','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(339,'Fiction:Werewolves','werewolves','OR','werewolf','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(340,'Fiction:Westerns','fiction:westerns','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(341,'Fiction:Westerns','western','OR','westerns','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(342,'Fiction:Witches&Warlocks','fiction:witches&warlocks','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(343,'Fiction:Witches&Warlocks','witch','OR','warlock','OR','witches','OR','warlocks','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(344,'Fiction:Women','fiction:women','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(345,'Fiction:Women','women','OR','chick-lit','OR','romance','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(346,'Fiction:Young Adult','fiction:youngadult','OR','fiction:youngadult','OR','ya','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(347,'Fiction:Young Adult','youngadult','OR','youngadult','OR','youth','OR','juvenile','OR','teenager');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(348,'Fiction:Zombies','fiction:zombies','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(349,'Fiction:Zombies','zombies','OR','zombie','OR','NONE','OR','NONE','OR','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(350,'Poetry','poetry','OR','poem','OR','poet','OR','non-prose','OR','prose');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_fiction VALUES(351,'Poetry','poetry','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                COMMIT; ")
    my_cursor.execute(mysql)
    log("Seed Rows Added to Table _dg_genre_tag_rules_fiction")

    mysql = str("\
                BEGIN TRANSACTION;\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(1,'Factual:Antiques&Collectibles','factual','AND','antique','AND','collectible','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(2,'Factual:Antiques&Collectibles','factual:antiques&collectibles','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(3,'Factual:Architecture-General','factual','AND','architecture','AND','general','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(4,'Factual:Architecture-General','factual:architecture-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(5,'Factual:Architecture-Historic Preservation','factual','AND','architecture','AND','historic','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(6,'Factual:Architecture-Historic Preservation','factual:architecture-historicpreservation','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(7,'Factual:Architecture-History','factual','AND','architecture','AND','history','AND','historical','AND','ancient');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(8,'Factual:Architecture-History','factual:architecture-history','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(9,'Factual:Art-Drawing','factual','AND','art','AND','drawing','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(10,'Factual:Art-Drawing','factual:art-drawing','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(11,'Factual:Art-Fashion','factual','AND','art','AND','fashion','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(12,'Factual:Art-Fashion','factual:art-fashion','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(13,'Factual:Art-Fine Arts','factual','AND','art','AND','fine','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(14,'Factual:Art-Fine Arts','factual:art-finearts','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(15,'Factual:Art-General','factual','AND','art','AND','drawing','AND','fashion','AND','fine');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(16,'Factual:Art-General','factual:art-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(17,'Factual:Art-History','factual','AND','art','AND','history','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(18,'Factual:Art-History','factual:art-history','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(19,'Factual:Art-Painting','factual','AND','art','AND','painting','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(20,'Factual:Art-Painting','factual:art-painting','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(21,'Factual:Art-Reference','factual','AND','art','AND','reference','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(22,'Factual:Art-Reference','factual:art-reference','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(23,'Factual:Art-Religious','factual','AND','art','AND','religious','AND','religion','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(24,'Factual:Art-Religious','factual:art-religious','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(25,'Factual:Art-Sculpture','factual','AND','art','AND','sculpture','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(26,'Factual:Art-Sculpture','factual:art-sculpture','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(27,'Factual:Art-Techniques','factual','AND','art','AND','technique','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(28,'Factual:Art-Techniques','factual:art-techniques','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(29,'Factual:Biography&Autobiography','factual','AND','biography','AND','biographical','AND','autobiography','AND','autobiographical');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(30,'Factual:Biography&Autobiography','factual:biography&autobiography','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(31,'Factual:Body&Mind&Spirit-General','factual','AND','body','AND','mind','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(32,'Factual:Body&Mind&Spirit-General','factual:body&mind&spirit-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(33,'Factual:Business&Economics-Accounting','factual','AND','accounting','AND','business','AND','economics','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(34,'Factual:Business&Economics-Accounting','factual:business&economics-accounting','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(35,'Factual:Business&Economics-Economics','factual','AND','economics','AND','business','AND','economy','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(36,'Factual:Business&Economics-Economics','factual:business&economics-economics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(37,'Factual:Business&Economics-Management','factual','AND','business','AND','management','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(38,'Factual:Business&Economics-Management','factual:business&economics-management','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(39,'Factual:Business&Economics-Marketing','factual','AND','business','AND','marketing','AND','sales','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(40,'Factual:Business&Economics-Marketing','factual:business&economics-marketing','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(41,'Factual:Computers-General','factual','AND','computers','AND','computing','AND','hardware','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(42,'Factual:Computers-General','factual:computers-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(43,'Factual:Computers-Languages','factual','AND','computer','AND','language','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(44,'Factual:Computers-Languages','factual:computers-languages','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(45,'Factual:Computers-Security','factual','AND','computer','AND','security','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(46,'Factual:Computers-Security','factual:computers-security','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(47,'Factual:Computers-Software','factual','AND','software','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(48,'Factual:Computers-Software','factual:computers-software','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(49,'Factual:Cooking-General','factual','AND','cooking','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(50,'Factual:Cooking-General','factual:cooking-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(51,'Factual:Crafts&Hobbies-General','factual','AND','crafts','AND','hobbies','AND','boat','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(52,'Factual:Crafts&Hobbies-General','factual:crafts&hobbies-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(53,'Factual:Drama-General','factual','AND','drama','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(54,'Factual:Drama-General','factual:drama-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(55,'Factual:Education-General','factual','AND','education','AND','teaching','AND','educational','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(56,'Factual:Education-General','factual:education-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(57,'Factual:Family&Relationships-General','factual','AND','family','AND','relationships','AND','marriage','AND','divorce');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(58,'Factual:Family&Relationships-General','factual:family&relationships-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(59,'Factual:Foreign Language Study-General','factual','AND','foreign','AND','language','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(60,'Factual:Foreign Language Study-General','factual:foreignlanguagestudy-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(61,'Factual:Games-General','factual','AND','games','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(62,'Factual:Games-General','factual:games-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(63,'Factual:Gardening-General','factual','AND','gardening','AND','horticulture','AND','gardener','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(64,'Factual:Gardening-General','factual:gardening-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(65,'Factual:Health&Fitness-General','factual','AND','health','AND','fitness','AND','diseases','AND','yoga');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(66,'Factual:Health&Fitness-General','factual:health&fitness-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(67,'Factual:History-General','factual','AND','history','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(68,'Factual:History-General','factual:history-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(69,'Factual:House&Home-Do-It-Yourself-Carpentry','factual','AND','diy','AND','carpentry','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(70,'Factual:House&Home-Do-It-Yourself-Carpentry','factual:house&home-do-it-yourself-carpentry','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(71,'Factual:House&Home-Do-It-Yourself-Electrical','factual','AND','diy','AND','electrical','AND','electricity','AND','wiring');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(72,'Factual:House&Home-Do-It-Yourself-Electrical','factual:house&home-do-it-yourself-electrical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(73,'Factual:House&Home-Do-It-Yourself-General','factual','AND','diy','AND','carpentry','AND','electrical','AND','plumbing');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(74,'Factual:House&Home-Do-It-Yourself-General','factual:house&home-do-it-yourself-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(75,'Factual:House&Home-Do-It-Yourself-Plumbing','factual','AND','diy','AND','plumbing','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(76,'Factual:House&Home-Do-It-Yourself-Plumbing','factual:house&home-do-it-yourself-plumbing','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(77,'Factual:Humor-General','factual','AND','humor','AND','humour','AND','comedy','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(78,'Factual:Humor-General','factual:humor-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(79,'Factual:Juvenile-General','factual','AND','juvenile','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(80,'Factual:Juvenile-General','factual:juvenile-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(81,'Factual:Language Arts-General','factual','AND','language','AND','arts','AND','reading','AND','spelling');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(82,'Factual:Language Arts-General','factual:languagearts-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(83,'Factual:Law-General','factual','AND','law','AND','jurisprudence','AND','arbitration','AND','courts');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(84,'Factual:Law-General','factual:law-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(85,'Factual:Literary Collections-General','factual','AND','literary','AND','collection','AND','criticism','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(86,'Factual:Literary Collections-General','factual:literarycollections-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(87,'Factual:Literary Criticism','factual','AND','literary','AND','criticism','AND','collection','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(88,'Factual:Literary Criticism','factual:literarycriticism','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(89,'Factual:Mathematics-General','factual','AND','math','AND','calculus','AND','algebra','AND','geometry');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(90,'Factual:Mathematics-General','factual:mathematics-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(91,'Factual:Medical-Dentistry','factual','AND','dentistry','AND','dental','AND','orthodontic','AND','periodontic');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(92,'Factual:Medical-Dentistry','factual:medical-dentistry','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(93,'Factual:Medical-General','factual','AND','medical','AND','medicine','AND','nursing','AND','surgery');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(94,'Factual:Medical-General','factual:medical-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(95,'Factual:Music-General','factual','AND','music','AND','biography','AND','autobiography','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(96,'Factual:Music-General','factual:music-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(97,'Factual:Nature-Animals','factual','AND','nature','AND','animals','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(98,'Factual:Nature-Animals','factual:nature-animals','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(99,'Factual:Nature-General','factual','AND','nature','AND','animals','AND','botony','AND','plants');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(100,'Factual:Nature-General','factual:nature-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(101,'Factual:Nature-Plants','factual','AND','plants','AND','botony','AND','flora','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(102,'Factual:Nature-Plants','factual:nature-plants','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(103,'Factual:Pets-General','factual','AND','pet','AND','cat','AND','dog','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(104,'Factual:Pets-General','factual:pets-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(105,'Factual:Philosophy-General','factual','AND','philosphy','AND','epistemology','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(106,'Factual:Philosophy-General','factual:philosophy-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(107,'Factual:Philosophy-Religious','factual','AND','religion','AND','religious','AND','art','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(108,'Factual:Philosophy-Religious','factual:philosophy-religious','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(109,'Factual:Political Science-General','factual','AND','politics','AND','civics','AND','politicalscience','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(110,'Factual:Political Science-General','factual:politicalscience-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(111,'Factual:Psychology-General','factual','AND','psychology','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(112,'Factual:Psychology-General','factual:psychology-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(113,'Factual:Reference','factual','AND','reference','AND','encyclopedia','AND','dictionary','AND','maps');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(114,'Factual:Reference','factual:reference','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(115,'Factual:Religion','factual','AND','religion','AND','religious','AND','art','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(116,'Factual:Religion','factual:religion','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(117,'Factual:Science-Acoustics&Sound','factual','AND','science','AND','acoustics','AND','sound','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(118,'Factual:Science-Acoustics&Sound','factual:science-acoustics&sound','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(119,'Factual:Science-Applied Sciences','factual','AND','science','AND','applied','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(120,'Factual:Science-Applied Sciences','factual:science-appliedsciences','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(121,'Factual:Science-Astronomy','factual','AND','astronomy','AND','astrophisics','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(122,'Factual:Science-Astronomy','factual:science-astronomy','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(123,'Factual:Science-Astrophysics&Space Science','factual','AND','astrophisics','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(124,'Factual:Science-Astrophysics&Space Science','factual:science-astrophysics&spacescience','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(125,'Factual:Science-Biotechnology','factual','AND','biotechnology','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(126,'Factual:Science-Biotechnology','factual:science-biotechnology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(127,'Factual:Science-Chemistry-Analytic','factual','AND','chemistry','AND','analytic','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(128,'Factual:Science-Chemistry-Analytic','factual:science-chemistry-analytic','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(129,'Factual:Science-Chemistry-Clinical','factual','AND','chemistry','AND','clinical','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(130,'Factual:Science-Chemistry-Clinical','factual:science-chemistry-clinical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(131,'Factual:Science-Chemistry-General','factual','AND','chemistry','AND','general','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(132,'Factual:Science-Chemistry-General','factual:science-chemistry-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(133,'Factual:Science-Chemistry-Inorganic','factual','AND','chemistry','AND','inorganic','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(134,'Factual:Science-Chemistry-Inorganic','factual:science-chemistry-inorganic','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(135,'Factual:Science-Chemistry-Organic','factual','AND','chemistry','AND','organic','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(136,'Factual:Science-Chemistry-Organic','factual:science-chemistry-organic','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(137,'Factual:Science-Chemistry-Physical&Theoretical','factual','AND','chemistry','AND','physical','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(138,'Factual:Science-Chemistry-Physical&Theoretical','factual:science-chemistry-physical&theoretical','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(139,'Factual:Science-Geology','factual','AND','geology','AND','geophisics','AND','hydrology','AND','mineralogy');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(140,'Factual:Science-Geology','factual:science-geology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(141,'Factual:Science-History','factual','AND','science','AND','history','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(142,'Factual:Science-History','factual:science-history','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(143,'Factual:Science-Life Sciences-Anatomy&Physiology','factual','AND','anatomy','AND','physiology','AND','medical','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(144,'Factual:Science-Life Sciences-Anatomy&Physiology','factual:science-lifesciences-anatomy&physiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(145,'Factual:Science-Life Sciences-Bacteriology','factual','AND','bacteriology','AND','medical','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(146,'Factual:Science-Life Sciences-Bacteriology','factual:science-lifesciences-bacteriology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(147,'Factual:Science-Life Sciences-Biochemistry','factual','AND','biochemistry','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(148,'Factual:Science-Life Sciences-Biochemistry','factual:science-lifesciences-biochemistry','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(149,'Factual:Science-Life Sciences-Biology-Developmental Biology','factual','AND','biology','AND','developmental','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(150,'Factual:Science-Life Sciences-Biology-Developmental Biology','factual:science-lifesciences-biology-developmentalbiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(151,'Factual:Science-Life Sciences-Biology-General','factual','AND','biology','AND','general','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(152,'Factual:Science-Life Sciences-Biology-General','factual:science-lifesciences-biology-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(153,'Factual:Science-Life Sciences-Biology-Marine Biology','factual','AND','marine','AND','biology','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(154,'Factual:Science-Life Sciences-Biology-Marine Biology','factual:science-lifesciences-biology-marinebiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(155,'Factual:Science-Life Sciences-Biology-Microbiology','factual','AND','microbiology','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(156,'Factual:Science-Life Sciences-Biology-Microbiology','factual:science-lifesciences-biology-microbiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(157,'Factual:Science-Life Sciences-Biology-Molecular Biology','factual','AND','molecular','AND','biology','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(158,'Factual:Science-Life Sciences-Biology-Molecular Biology','factual:science-lifesciences-biology-molecularbiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(159,'Factual:Science-Life Sciences-Biophysics','factual','AND','biophysics','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(160,'Factual:Science-Life Sciences-Biophysics','factual:science-lifesciences-biophysics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(161,'Factual:Science-Life Sciences-Botany','factual','AND','botony','AND','horticulture','AND','gardening','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(162,'Factual:Science-Life Sciences-Botany','factual:science-lifesciences-botany','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(163,'Factual:Science-Life Sciences-Cytology','factual','AND','cytology','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(164,'Factual:Science-Life Sciences-Cytology','factual:science-lifesciences-cytology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(165,'Factual:Science-Life Sciences-Ecology','factual','AND','ecology','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(166,'Factual:Science-Life Sciences-Ecology','factual:science-lifesciences-ecology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(167,'Factual:Science-Life Sciences-Evolution','factual','AND','evolution','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(168,'Factual:Science-Life Sciences-Evolution','factual:science-lifesciences-evolution','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(169,'Factual:Science-Life Sciences-General','factual','AND','science','AND','life-science','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(170,'Factual:Science-Life Sciences-General','factual:science-lifesciences-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(171,'Factual:Science-Life Sciences-Genetics&Genomics','factual','AND','genetics','AND','genomics','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(172,'Factual:Science-Life Sciences-Genetics&Genomics','factual:science-lifesciences-genetics&genomics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(173,'Factual:Science-Life Sciences-Horticulture','factual','AND','horticulture','AND','gardening','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(174,'Factual:Science-Life Sciences-Horticulture','factual:science-lifesciences-horticulture','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(175,'Factual:Science-Life Sciences-Human Anatomy&Physiology','factual','AND','anatomy','AND','human','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(176,'Factual:Science-Life Sciences-Human Anatomy&Physiology','factual:science-lifesciences-humananatomy&physiology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(177,'Factual:Science-Life Sciences-Taxonomy','factual','AND','taxonomy','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(178,'Factual:Science-Life Sciences-Taxonomy','factual:science-lifesciences-taxonomy','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(179,'Factual:Science-Life Sciences-Zoology-Entomology','factual','AND','zoology','AND','entomology','AND','insects','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(180,'Factual:Science-Life Sciences-Zoology-Entomology','factual:science-lifesciences-zoology-entomology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(181,'Factual:Science-Life Sciences-Zoology-General','factual','AND','zoology','AND','general','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(182,'Factual:Science-Life Sciences-Zoology-General','factual:science-lifesciences-zoology-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(183,'Factual:Science-Life Sciences-Zoology-Ichthyology','factual','AND','zoology','AND','ichthyology','AND','fish','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(184,'Factual:Science-Life Sciences-Zoology-Ichthyology','factual:science-lifesciences-zoology-ichthyology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(185,'Factual:Science-Life Sciences-Zoology-Invertebrates','factual','AND','zoology','AND','invertebrate','AND','chordate','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(186,'Factual:Science-Life Sciences-Zoology-Invertebrates','factual:science-lifesciences-zoology-invertebrates','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(187,'Factual:Science-Life Sciences-Zoology-Mammals','factual','AND','zoology','AND','mammal','AND','mammalian','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(188,'Factual:Science-Life Sciences-Zoology-Mammals','factual:science-lifesciences-zoology-mammals','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(189,'Factual:Science-Life Sciences-Zoology-Ornithology','factual','AND','zoology','AND','ornithology','AND','birds','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(190,'Factual:Science-Life Sciences-Zoology-Ornithology','factual:science-lifesciences-zoology-ornithology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(191,'Factual:Science-Life Sciences-Zoology-Primatology','factual','AND','zoology','AND','primatology','AND','primates','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(192,'Factual:Science-Life Sciences-Zoology-Primatology','factual:science-lifesciences-zoology-primatology','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(193,'Factual:Science-Mathematical Physics','factual','AND','physics','AND','mathematical','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(194,'Factual:Science-Mathematical Physics','factual:science-mathematicalphysics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(195,'Factual:Science-Nuclear Physics','factual','AND','physics','AND','nuclear','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(196,'Factual:Science-Nuclear Physics','factual:science-nuclearphysics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(197,'Factual:Science-Physics','factual','AND','physics','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(198,'Factual:Science-Physics','factual:science-physics','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(199,'Factual:Science-Reference','factual','AND','science','AND','reference','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(200,'Factual:Science-Reference','factual:science-reference','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(201,'Factual:Self-Help-Abuse','factual','AND','self-help','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(202,'Factual:Self-Help-Abuse','factual:self-help-abuse','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(203,'Factual:Social Science-General','factual','AND','social','AND','science','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(204,'Factual:Social Science-General','factual:socialscience-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(205,'Factual:Sports&Recreation-General','factual','AND','sports','AND','recreation','AND','sport','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(206,'Factual:Sports&Recreation-General','factual:sports&recreation-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(207,'Factual:Study Aids-General','factual','AND','study','AND','aid','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(208,'Factual:Study Aids-General','factual:studyaids-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(209,'Factual:Technology-General','factual','AND','technology','AND','engineering','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(210,'Factual:Technology-General','factual:technology-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(211,'Factual:Transportation-General','factual','AND','transportation','AND','aviation','AND','automotive','AND','railroad');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(212,'Factual:Transportation-General','factual:transportation-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(213,'Factual:Travel-General','factual','AND','travel','AND','NONE','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(214,'Factual:Travel-General','factual:travel-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(215,'Factual:True Crime-Espionage','factual','AND','crime','AND','espionage','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(216,'Factual:True Crime-Espionage','factual:truecrime-espionage','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(217,'Factual:True Crime-General','factual','AND','crime','AND','espionage','AND','murder','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(218,'Factual:True Crime-General','factual:truecrime-general','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(219,'Factual:True Crime-Murder','factual','AND','crime','AND','murder','AND','NONE','AND','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(220,'Factual:True Crime-Murder','factual:truecrime-murder','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(221,'Factual:Young Adult','factual','AND','juvenile','AND','youth','AND','ya','AND','youngadult');\
                INSERT OR IGNORE INTO _dg_genre_tag_rules_factual VALUES(222,'Factual:Young Adult','factual:youngadult','NONE','NONE','NONE','NONE','NONE','NONE','NONE','NONE');\
                COMMIT; ")
    my_cursor.execute(mysql)
    log("Seed Rows Added to Table _dg_genre_tag_rules_factual")


    mysql = str("\
            BEGIN TRANSACTION;\
            DELETE FROM _dg_genre_tag_rules_factual WHERE tag_keyword_1 NOT IN(SELECT nf_keyword FROM _dg_nf_language_keywords);\
            COMMIT; ")
    my_cursor.execute(mysql)

    mysql = str("\
                BEGIN TRANSACTION;\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(1,'a. grove day','NONE','FACTUAL:BIOGRAPHY&AUTOBIOGRAPHY');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(2,'a. lee martinez','Fiction:Fantasy','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(3,'a. manette ansay','Fiction:Romance-Historical','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(4,'a. meredith walters','Fiction:Romance','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(5,'a. michael matin','Fiction:Classics','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(6,'a. scott berg','NONE','FACTUAL:BIOGRAPHY&AUTOBIOGRAPHY');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(7,'a. warneke','Fiction:Romance','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(8,'a.a. bell','Fiction:Fantasy','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(9,'a.c. crispin','Fiction:Science&Fantasy','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(10,'a.c. dillon','Fiction:Suspense&Thriller','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(11,'a.c. mason','Fiction:Horror','NONE');\
                INSERT OR IGNORE INTO _dg_genre_author_rules VALUES(12,'a.c. warneke','Fiction:Romance','NONE');\
                COMMIT; ")
    my_cursor.execute(mysql)
    log("Seed Rows Added to Table _dg_genre_author_rules")
   #-----------------------------------------------------------------------------------------------------------------
def Make_Author_Names_Lowercase(my_db,my_cursor,log):

    my_rules_sql = []

    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'A','a'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'B','b'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'C','c'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'D','d'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'E','e'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'F','f'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'G','g'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'H','h'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'I','i'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'J','j'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'K','k'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'L','l'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'M','m'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'N','n'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'O','o'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'P','p'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'Q','q'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'R','r'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'S','s'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'T','t'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'U','u'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'V','v'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'W','w'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'X','x'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'Y','y'))")
    my_rules_sql.append(mysql)
    mysql = str("UPDATE _dg_genre_author_rules SET author = (replace(author,'Z','z'))")
    my_rules_sql.append(mysql)

  #---------------------------
    my_cursor.execute("begin")  #apsw
    for row in my_rules_sql:
        mysql = str(row)
        try:
            my_cursor.execute(mysql)
        except:
            pass
    #END FOR
    try:
        my_cursor.execute("commit")  #apsw
    except:
        pass

   #-----------------------------------------------------------------------------------------------------------------
def _purge_work_tables(my_db,my_cursor,log):       #new version 3.6.25

    mysql = "DELETE FROM _dg_books"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)
    mysql = "DELETE FROM _dg_books_factual"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)
    mysql = "DELETE FROM _dg_books_tagnames"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)
    mysql = "DELETE FROM _dg_books_tagrules"
    Execute_mysql_with_commit_generic(my_db, my_cursor, mysql, log)


   #-----------------------------------------------------------------------------------------------------------------
   #-----------------------------------------------------------------------------------------------------------------
   #-----------------------------------------------------------------------------------------------------------------
#END of derivegenres.py
#=================================================================================

