Add unique constraint, None option
This commit is contained in:
@@ -1,3 +1,12 @@
|
||||
__all__ = ['commons', 'datalite_decorator', 'fetch', 'migrations', 'datalite']
|
||||
__all__ = ['commons', 'datalite_decorator', 'fetch', 'migrations', 'datalite', 'constraints']
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
from .datalite_decorator import datalite
|
||||
|
||||
|
||||
@dataclass
|
||||
class Student:
|
||||
id_: int
|
||||
name: str
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
from dataclasses import Field
|
||||
from typing import Any, Optional, Dict, List
|
||||
from .constraints import Unique
|
||||
import sqlite3 as sql
|
||||
|
||||
|
||||
type_table: Dict[Optional[type], str] = {None: "NULL", int: "INTEGER", float: "REAL",
|
||||
str: "TEXT", bytes: "BLOB"}
|
||||
type_table.update({Unique[key]: f"{value} NOT NULL UNIQUE" for key, value in type_table.items()})
|
||||
|
||||
|
||||
def _convert_type(type_: Optional[type], type_overload: Dict[Optional[type], str]) -> str:
|
||||
"""
|
||||
Given a Python type, return the str name of its
|
||||
@@ -30,7 +36,9 @@ def _convert_sql_format(value: Any) -> str:
|
||||
>>> _convert_sql_format("John Smith")
|
||||
'"John Smith"'
|
||||
"""
|
||||
if isinstance(value, str):
|
||||
if value is None:
|
||||
return "NULL"
|
||||
elif isinstance(value, str):
|
||||
return f'"{value}"'
|
||||
elif isinstance(value, bytes):
|
||||
return '"' + str(value).replace("b'", "")[:-1] + '"'
|
||||
@@ -82,5 +90,5 @@ def _create_table(class_: type, cursor: sql.Cursor, type_overload: Dict[Optional
|
||||
sql_fields = "obj_id INTEGER PRIMARY KEY AUTOINCREMENT, " + sql_fields
|
||||
cursor.execute(f"CREATE TABLE IF NOT EXISTS {class_.__name__.lower()} ({sql_fields});")
|
||||
|
||||
type_table: Dict[Optional[type], str] = {None: "NULL", int: "INTEGER", float: "REAL",
|
||||
str: "TEXT", bytes: "BLOB"}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"""
|
||||
datalite.constraints module introduces constraint
|
||||
types that can be used to hint field variables,
|
||||
that can be used to signal datalite decorator
|
||||
constraints in the database.
|
||||
"""
|
||||
from typing import TypeVar, Union, Tuple
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
class ConstraintFailedError(Exception):
|
||||
"""
|
||||
This exception is raised when a Constraint fails.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
Dataclass fields hinted with this type signals
|
||||
datalite that the bound column of this
|
||||
field in the table is NOT NULL and UNIQUE.
|
||||
"""
|
||||
Unique = Union[Tuple[T], T]
|
||||
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
Defines the Datalite decorator that can be used to convert a dataclass to
|
||||
a class bound to a sqlite3 database.
|
||||
"""
|
||||
|
||||
from sqlite3.dbapi2 import IntegrityError
|
||||
from typing import Dict, Optional, List, Callable
|
||||
from dataclasses import Field, asdict
|
||||
import sqlite3 as sql
|
||||
|
||||
from constraints import ConstraintFailedError
|
||||
from .commons import _convert_sql_format, _convert_type, _create_table, type_table
|
||||
|
||||
|
||||
@@ -22,11 +24,14 @@ def _create_entry(self) -> None:
|
||||
table_name: str = self.__class__.__name__.lower()
|
||||
kv_pairs = [item for item in asdict(self).items()]
|
||||
kv_pairs.sort(key=lambda item: item[0]) # Sort by the name of the fields.
|
||||
cur.execute(f"INSERT INTO {table_name}("
|
||||
f"{', '.join(item[0] for item in kv_pairs)})"
|
||||
f" VALUES ({', '.join(_convert_sql_format(item[1]) for item in kv_pairs)});")
|
||||
self.__setattr__("obj_id", cur.lastrowid)
|
||||
con.commit()
|
||||
try:
|
||||
cur.execute(f"INSERT INTO {table_name}("
|
||||
f"{', '.join(item[0] for item in kv_pairs)})"
|
||||
f" VALUES ({', '.join(_convert_sql_format(item[1]) for item in kv_pairs)});")
|
||||
self.__setattr__("obj_id", cur.lastrowid)
|
||||
con.commit()
|
||||
except IntegrityError:
|
||||
raise ConstraintFailedError("A constraint has failed.")
|
||||
|
||||
|
||||
def _update_entry(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user