Сообщить об ошибке.

Хранение типов Python в базах данных SQLite3

База данных SQLite3 изначально поддерживает только ограниченный набор типов Python. Чтобы использовать другие типы Python с SQLite, необходимо адаптировать их к одному из поддерживаемых типов модуля sqlite3 для SQLite: одному из None, int, float, str, bytes.

Есть два способа включить модуль sqlite3 для адаптации пользовательского типа Python к одному из поддерживаемых.

Адаптировать объект под типы SQLite.

Предположим, есть такой класс:

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

Теперь необходимо сохранить точку в одном столбце SQLite. Сначала нужно выбрать один из поддерживаемых типов SQLite, который будет использоваться для представления точки. Давайте просто используем str и разделим координаты точкой с запятой. Затем нужно дать классу метод __conform__(self, protocol), который должен возвращать преобразованное значение. Протокол protocol параметров будет PrepareProtocol.

import sqlite3

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

    def __conform__(self, protocol):
        if protocol is sqlite3.PrepareProtocol:
            return "%f;%f" % (self.x, self.y)

con = sqlite3.connect(":memory:")
cur = con.cursor()

p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])

con.close()

Зарегистрировать адаптер.

Другая возможность - создать функцию, которая преобразует тип в строковое представление, а потом ее зарегистрировать с помощью sqlite3.register_adapter().

import sqlite3

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

def adapt_point(point):
    return "%f;%f" % (point.x, point.y)

sqlite3.register_adapter(Point, adapt_point)

con = sqlite3.connect(":memory:")
cur = con.cursor()

p = Point(4.0, -3.2)
cur.execute("select ?", (p,))
print(cur.fetchone()[0])

con.close()

Модуль sqlite3 имеет два адаптера по умолчанию для встроенных в Python типов datetime.date() и datetime.datetime(). Теперь предположим, что необходимо хранить объекты datetime.datetime не в формате ISO, а в виде метки времени Unix.

import sqlite3
import time, datetime

def adapt_datetime(ts):
    return time.mktime(ts.timetuple())

sqlite3.register_adapter(datetime.datetime, adapt_datetime)

con = sqlite3.connect(":memory:")
cur = con.cursor()

now = datetime.datetime.now()
cur.execute("select ?", (now,))
print(cur.fetchone()[0])

con.close()