convert torrent table flags column from bitflag to independent indexed columns

This commit is contained in:
nyaadev 2018-04-08 04:27:17 +02:00
parent c786bd20f8
commit 268ca12321
3 changed files with 116 additions and 62 deletions

View File

@ -0,0 +1,96 @@
"""Convert bitflags to seperate indexed columns
Revision ID: ecb0b3b88142
Revises: 6cc823948c5a
Create Date: 2018-04-08 02:52:44.178958
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
import sys
# revision identifiers, used by Alembic.
revision = 'ecb0b3b88142'
down_revision = '6cc823948c5a'
branch_labels = None
depends_on = None
def upgrade():
op.execute(
"ALTER TABLE nyaa_torrents "
"ADD COLUMN anonymous BOOL NOT NULL, "
"ADD COLUMN banned BOOL NOT NULL, "
"ADD COLUMN comment_locked BOOL NOT NULL, "
"ADD COLUMN complete BOOL NOT NULL, "
"ADD COLUMN deleted BOOL NOT NULL, "
"ADD COLUMN hidden BOOL NOT NULL, "
"ADD COLUMN remake BOOL NOT NULL, "
"ADD COLUMN trusted BOOL NOT NULL;"
)
op.create_index(op.f('ix_nyaa_torrents_anonymous'), 'nyaa_torrents', ['anonymous'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_banned'), 'nyaa_torrents', ['banned'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_comment_locked'), 'nyaa_torrents', ['comment_locked'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_complete'), 'nyaa_torrents', ['complete'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_deleted'), 'nyaa_torrents', ['deleted'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_hidden'), 'nyaa_torrents', ['hidden'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_remake'), 'nyaa_torrents', ['remake'], unique=False)
op.create_index(op.f('ix_nyaa_torrents_trusted'), 'nyaa_torrents', ['trusted'], unique=False)
op.drop_index('ix_nyaa_torrents_flags', table_name='nyaa_torrents')
op.create_index(op.f('ix_nyaa_torrents_uploader_id'), 'nyaa_torrents', ['uploader_id'], unique=False)
op.drop_index('uploader_flag_idx', table_name='nyaa_torrents')
op.execute('UPDATE nyaa_torrents SET anonymous = TRUE WHERE flags & 1 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET hidden = TRUE WHERE flags & 2 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET trusted = TRUE WHERE flags & 4 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET remake = TRUE WHERE flags & 8 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET complete = TRUE WHERE flags & 16 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET deleted = TRUE WHERE flags & 32 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET banned = TRUE WHERE flags & 64 IS TRUE;')
op.execute('UPDATE nyaa_torrents SET comment_locked = TRUE WHERE flags & 128 IS TRUE;')
op.drop_column('nyaa_torrents', 'flags')
op.execute(
"ALTER TABLE sukebei_torrents "
"ADD COLUMN anonymous BOOL NOT NULL, "
"ADD COLUMN banned BOOL NOT NULL, "
"ADD COLUMN comment_locked BOOL NOT NULL, "
"ADD COLUMN complete BOOL NOT NULL, "
"ADD COLUMN deleted BOOL NOT NULL, "
"ADD COLUMN hidden BOOL NOT NULL, "
"ADD COLUMN remake BOOL NOT NULL, "
"ADD COLUMN trusted BOOL NOT NULL;"
)
op.create_index(op.f('ix_sukebei_torrents_anonymous'), 'sukebei_torrents', ['anonymous'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_banned'), 'sukebei_torrents', ['banned'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_comment_locked'), 'sukebei_torrents', ['comment_locked'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_complete'), 'sukebei_torrents', ['complete'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_deleted'), 'sukebei_torrents', ['deleted'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_hidden'), 'sukebei_torrents', ['hidden'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_remake'), 'sukebei_torrents', ['remake'], unique=False)
op.create_index(op.f('ix_sukebei_torrents_trusted'), 'sukebei_torrents', ['trusted'], unique=False)
op.drop_index('ix_sukebei_torrents_flags', table_name='sukebei_torrents')
op.create_index(op.f('ix_sukebei_torrents_uploader_id'), 'sukebei_torrents', ['uploader_id'], unique=False)
op.drop_index('uploader_flag_idx', table_name='sukebei_torrents')
op.execute('UPDATE sukebei_torrents SET anonymous = TRUE WHERE flags & 1 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET hidden = TRUE WHERE flags & 2 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET trusted = TRUE WHERE flags & 4 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET remake = TRUE WHERE flags & 8 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET complete = TRUE WHERE flags & 16 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET deleted = TRUE WHERE flags & 32 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET banned = TRUE WHERE flags & 64 IS TRUE;')
op.execute('UPDATE sukebei_torrents SET comment_locked = TRUE WHERE flags & 128 IS TRUE;')
op.drop_column('sukebei_torrents', 'flags')
def downgrade():
print("downgrade not supported")
sys.exit(1)

View File

@ -67,42 +67,6 @@ class DeclarativeHelperBase(object):
return cls._table_prefix(cls.__tablename_base__) return cls._table_prefix(cls.__tablename_base__)
class FlagProperty(object):
''' This class will act as a wrapper between the given flag and the class's
flag collection. '''
def __init__(self, flag, flags_attr='flags'):
self._flag = flag
self._flags_attr_name = flags_attr
def _get_flags(self, instance):
return getattr(instance, self._flags_attr_name)
def _set_flags(self, instance, value):
return setattr(instance, self._flags_attr_name, value)
def __get__(self, instance, owner_class):
if instance is None:
raise AttributeError()
return bool(self._get_flags(instance) & self._flag)
def __set__(self, instance, value):
new_flags = (self._get_flags(instance) & ~self._flag) | (bool(value) and self._flag)
self._set_flags(instance, new_flags)
class TorrentFlags(IntEnum):
NONE = 0
ANONYMOUS = 1
HIDDEN = 2
TRUSTED = 4
REMAKE = 8
COMPLETE = 16
DELETED = 32
BANNED = 64
COMMENT_LOCKED = 128
class TorrentBase(DeclarativeHelperBase): class TorrentBase(DeclarativeHelperBase):
__tablename_base__ = 'torrents' __tablename_base__ = 'torrents'
@ -116,7 +80,6 @@ class TorrentBase(DeclarativeHelperBase):
filesize = db.Column(db.BIGINT, default=0, nullable=False, index=True) filesize = db.Column(db.BIGINT, default=0, nullable=False, index=True)
encoding = db.Column(db.String(length=32), nullable=False) encoding = db.Column(db.String(length=32), nullable=False)
flags = db.Column(db.Integer, default=0, nullable=False, index=True)
@declarative.declared_attr @declarative.declared_attr
def uploader_id(cls): def uploader_id(cls):
@ -147,7 +110,6 @@ class TorrentBase(DeclarativeHelperBase):
@declarative.declared_attr @declarative.declared_attr
def __table_args__(cls): def __table_args__(cls):
return ( return (
Index(cls._table_prefix('uploader_flag_idx'), 'uploader_id', 'flags'),
ForeignKeyConstraint( ForeignKeyConstraint(
['main_category_id', 'sub_category_id'], ['main_category_id', 'sub_category_id'],
[cls._table_prefix('sub_categories.main_category_id'), [cls._table_prefix('sub_categories.main_category_id'),
@ -253,14 +215,14 @@ class TorrentBase(DeclarativeHelperBase):
# Flag properties below # Flag properties below
anonymous = FlagProperty(TorrentFlags.ANONYMOUS) anonymous = db.Column(db.Boolean, nullable=False, default=False, index=True)
hidden = FlagProperty(TorrentFlags.HIDDEN) hidden = db.Column(db.Boolean, nullable=False, default=False, index=True)
deleted = FlagProperty(TorrentFlags.DELETED) deleted = db.Column(db.Boolean, nullable=False, default=False, index=True)
banned = FlagProperty(TorrentFlags.BANNED) banned = db.Column(db.Boolean, nullable=False, default=False, index=True)
trusted = FlagProperty(TorrentFlags.TRUSTED) trusted = db.Column(db.Boolean, nullable=False, default=False, index=True)
remake = FlagProperty(TorrentFlags.REMAKE) remake = db.Column(db.Boolean, nullable=False, default=False, index=True)
complete = FlagProperty(TorrentFlags.COMPLETE) complete = db.Column(db.Boolean, nullable=False, default=False, index=True)
comment_locked = FlagProperty(TorrentFlags.COMMENT_LOCKED) comment_locked = db.Column(db.Boolean, nullable=False, default=False, index=True)
# Class methods # Class methods

View File

@ -8,6 +8,7 @@ import sqlalchemy
import sqlalchemy_fulltext.modes as FullTextMode import sqlalchemy_fulltext.modes as FullTextMode
from elasticsearch import Elasticsearch from elasticsearch import Elasticsearch
from elasticsearch_dsl import Q, Search from elasticsearch_dsl import Q, Search
from sqlalchemy.sql.expression import false
from sqlalchemy_fulltext import FullTextSearch from sqlalchemy_fulltext import FullTextSearch
from nyaa import models from nyaa import models
@ -294,9 +295,9 @@ def search_db(term='', user=None, sort='id', order='desc', category='0_0',
filter_keys = { filter_keys = {
'0': None, '0': None,
'1': (models.TorrentFlags.REMAKE, False), '1': (models.Torrent.remake, False),
'2': (models.TorrentFlags.TRUSTED, True), '2': (models.Torrent.trusted, True),
'3': (models.TorrentFlags.COMPLETE, True) '3': (models.Torrent.complete, True)
} }
sentinel = object() sentinel = object()
@ -356,8 +357,7 @@ def search_db(term='', user=None, sort='id', order='desc', category='0_0',
if not admin: if not admin:
# Hide all DELETED torrents if regular user # Hide all DELETED torrents if regular user
qpc.filter(models.Torrent.flags.op('&')( qpc.filter(models.Torrent.deleted == false())
int(models.TorrentFlags.DELETED)).is_(False))
# If logged in user is not the same as the user being viewed, # If logged in user is not the same as the user being viewed,
# show only torrents that aren't hidden or anonymous # show only torrents that aren't hidden or anonymous
# #
@ -367,24 +367,21 @@ def search_db(term='', user=None, sort='id', order='desc', category='0_0',
# On RSS pages in user view, # On RSS pages in user view,
# show only torrents that aren't hidden or anonymous no matter what # show only torrents that aren't hidden or anonymous no matter what
if not same_user or rss: if not same_user or rss:
qpc.filter(models.Torrent.flags.op('&')( qpc.filter((models.Torrent.hidden == false()) &
int(models.TorrentFlags.HIDDEN | models.TorrentFlags.ANONYMOUS)).is_(False)) (models.Torrent.anonymous == false()))
# General view (homepage, general search view) # General view (homepage, general search view)
else: else:
if not admin: if not admin:
# Hide all DELETED torrents if regular user # Hide all DELETED torrents if regular user
qpc.filter(models.Torrent.flags.op('&')( qpc.filter(models.Torrent.deleted == false())
int(models.TorrentFlags.DELETED)).is_(False))
# If logged in, show all torrents that aren't hidden unless they belong to you # If logged in, show all torrents that aren't hidden unless they belong to you
# On RSS pages, show all public torrents and nothing more. # On RSS pages, show all public torrents and nothing more.
if logged_in_user and not rss: if logged_in_user and not rss:
qpc.filter( qpc.filter((models.Torrent.hidden == false()) |
(models.Torrent.flags.op('&')(int(models.TorrentFlags.HIDDEN)).is_(False)) | (models.Torrent.uploader_id == logged_in_user.id))
(models.Torrent.uploader_id == logged_in_user.id))
# Otherwise, show all torrents that aren't hidden # Otherwise, show all torrents that aren't hidden
else: else:
qpc.filter(models.Torrent.flags.op('&')( qpc.filter(models.Torrent.hidden == false())
int(models.TorrentFlags.HIDDEN)).is_(False))
if main_category: if main_category:
qpc.filter(models.Torrent.main_category_id == main_cat_id) qpc.filter(models.Torrent.main_category_id == main_cat_id)
@ -393,8 +390,7 @@ def search_db(term='', user=None, sort='id', order='desc', category='0_0',
(models.Torrent.sub_category_id == sub_cat_id)) (models.Torrent.sub_category_id == sub_cat_id))
if filter_tuple: if filter_tuple:
qpc.filter(models.Torrent.flags.op('&')( qpc.filter(filter_tuple[0] == filter_tuple[1])
int(filter_tuple[0])).is_(filter_tuple[1]))
if term: if term:
for item in shlex.split(term, posix=False): for item in shlex.split(term, posix=False):