use mysql backend in config.dev

First off: This commit changes the default development database
backend to mysql. sqlite, however, is still completely supported
with the caveat that a user must now modify config.dev to use
the sqlite backend.

While looking into this, it was discovered that our SQLAlchemy
backend for mysql (mysql-connector) completely broke model
attributes when we switched to utf8mb4_bin (binary) -- it does
not correct the correct conversion to and from binary utf8mb4.

The new, replacement dependency mysqlclient does. mysqlclient
is also recommended in SQLAlchemy documentation as the "best"
one available.

The mysqlclient backend uses a different exception flow then
sqlite, and so tests expecting IntegrityError has to be modified
to expect OperationalError from sqlalchemy.exc.

So, for each model that we define, check keys that can't be
NULL and raise sqlalchemy.exc.IntegrityError if we have to.
This way we keep our exceptions uniform.

Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
Kevin Morris 2021-06-04 00:43:57 -07:00
parent d7481b9649
commit aecb649473
25 changed files with 363 additions and 135 deletions

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
@ -11,7 +12,19 @@ class AcceptedTerm:
User: User = None, Term: Term = None,
Revision: int = None):
self.User = User
if not self.User:
raise IntegrityError(
statement="Foreign key UserID cannot be null.",
orig="AcceptedTerms.UserID",
params=("NULL"))
self.Term = Term
if not self.Term:
raise IntegrityError(
statement="Foreign key TermID cannot be null.",
orig="AcceptedTerms.TermID",
params=("NULL"))
self.Revision = Revision

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.schema import ApiRateLimit as _ApiRateLimit
@ -8,8 +9,20 @@ class ApiRateLimit:
Requests: int = None,
WindowStart: int = None):
self.IP = IP
self.Requests = Requests
if self.Requests is None:
raise IntegrityError(
statement="Column Requests cannot be null.",
orig="ApiRateLimit.Requests",
params=("NULL"))
self.WindowStart = WindowStart
if self.WindowStart is None:
raise IntegrityError(
statement="Column WindowStart cannot be null.",
orig="ApiRateLimit.WindowStart",
params=("NULL"))
mapper(ApiRateLimit, _ApiRateLimit, primary_key=[_ApiRateLimit.c.IP])

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.schema import Groups
@ -6,6 +7,11 @@ from aurweb.schema import Groups
class Group:
def __init__(self, Name: str = None):
self.Name = Name
if not self.Name:
raise IntegrityError(
statement="Column Name cannot be null.",
orig="Groups.Name",
params=("NULL"))
mapper(Group, Groups)

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.schema import Licenses
@ -6,6 +7,11 @@ from aurweb.schema import Licenses
class License:
def __init__(self, Name: str = None):
self.Name = Name
if not self.Name:
raise IntegrityError(
statement="Column Name cannot be null.",
orig="Licenses.Name",
params=("NULL"))
mapper(License, Licenses)

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
@ -11,7 +12,19 @@ class Package:
Name: str = None, Version: str = None,
Description: str = None, URL: str = None):
self.PackageBase = PackageBase
if not self.PackageBase:
raise IntegrityError(
statement="Foreign key UserID cannot be null.",
orig="Packages.PackageBaseID",
params=("NULL"))
self.Name = Name
if not self.Name:
raise IntegrityError(
statement="Column Name cannot be null.",
orig="Packages.Name",
params=("NULL"))
self.Version = Version
self.Description = Description
self.URL = URL

View file

@ -1,5 +1,6 @@
from datetime import datetime
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
@ -12,6 +13,12 @@ class PackageBase:
Maintainer: User = None, Submitter: User = None,
Packager: User = None, **kwargs):
self.Name = Name
if not self.Name:
raise IntegrityError(
statement="Column Name cannot be null.",
orig="PackageBases.Name",
params=("NULL"))
self.Flagger = Flagger
self.Maintainer = Maintainer
self.Submitter = Submitter

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
@ -12,8 +13,26 @@ class PackageDependency:
DepName: str = None, DepDesc: str = None,
DepCondition: str = None, DepArch: str = None):
self.Package = Package
if not self.Package:
raise IntegrityError(
statement="Foreign key PackageID cannot be null.",
orig="PackageDependencies.PackageID",
params=("NULL"))
self.DependencyType = DependencyType
self.DepName = DepName # nullable=False
if not self.DependencyType:
raise IntegrityError(
statement="Foreign key DepTypeID cannot be null.",
orig="PackageDependencies.DepTypeID",
params=("NULL"))
self.DepName = DepName
if not self.DepName:
raise IntegrityError(
statement="Column DepName cannot be null.",
orig="PackageDependencies.DepName",
params=("NULL"))
self.DepDesc = DepDesc
self.DepCondition = DepCondition
self.DepArch = DepArch

View file

@ -1,5 +1,5 @@
from sqlalchemy.orm import mapper
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
from aurweb.models.group import Group

View file

@ -1,5 +1,5 @@
from sqlalchemy.orm import mapper
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
from aurweb.models.package_base import PackageBase

View file

@ -1,5 +1,5 @@
from sqlalchemy.orm import mapper
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
from aurweb.models.license import License

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.db import make_relationship
@ -12,8 +13,26 @@ class PackageRelation:
RelName: str = None, RelCondition: str = None,
RelArch: str = None):
self.Package = Package
if not self.Package:
raise IntegrityError(
statement="Foreign key PackageID cannot be null.",
orig="PackageRelations.PackageID",
params=("NULL"))
self.RelationType = RelationType
if not self.RelationType:
raise IntegrityError(
statement="Foreign key RelTypeID cannot be null.",
orig="PackageRelations.RelTypeID",
params=("NULL"))
self.RelName = RelName # nullable=False
if not self.RelName:
raise IntegrityError(
statement="Column RelName cannot be null.",
orig="PackageRelations.RelName",
params=("NULL"))
self.RelCondition = RelCondition
self.RelArch = RelArch

View file

@ -1,16 +1,20 @@
from sqlalchemy import Column, Integer
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import backref, mapper, relationship
from aurweb.db import make_random_value
from aurweb.db import make_random_value, query
from aurweb.models.user import User
from aurweb.schema import Sessions
class Session:
UsersID = Column(Integer, nullable=True)
def __init__(self, **kwargs):
self.UsersID = kwargs.get("UsersID")
if not query(User, User.ID == self.UsersID).first():
raise IntegrityError(
statement="Foreign key UsersID cannot be null.",
orig="Sessions.UsersID",
params=("NULL"))
self.SessionID = kwargs.get("SessionID")
self.LastUpdateTS = kwargs.get("LastUpdateTS")

View file

@ -1,3 +1,4 @@
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import mapper
from aurweb.schema import Terms
@ -8,7 +9,19 @@ class Term:
Description: str = None, URL: str = None,
Revision: int = None):
self.Description = Description
if not self.Description:
raise IntegrityError(
statement="Column Description cannot be null.",
orig="Terms.Description",
params=("NULL"))
self.URL = URL
if not self.URL:
raise IntegrityError(
statement="Column URL cannot be null.",
orig="Terms.URL",
params=("NULL"))
self.Revision = Revision