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

Преобразовать тип SQLite в пользовательский тип Python

Адаптеры позволяют [отправлять пользовательские типы Python в SQLite. Но чтобы сделать его действительно полезным, нужно заставить работать по схеме Python to SQLite to Python.

Вернемся к классу Point(), там мы сохранили координаты x и y через точку с запятой ';' в виде строки в базу SQLite.

Во-первых, надо определить функцию-преобразователь, которая принимает строку в качестве параметра и строит из нее объект Point().

Примечание. Функции конвертеры всегда вызываются с помощью объекта байтов, независимо от того, в каком типе данных вы отправили значение в SQLite.

def convert_point(s):
    x, y = map(float, s.split(b";"))
    return Point(x, y)

Теперь нужно, чтобы модуль sqlite3 знал, то что выбирается из базы данных, на самом деле является точкой. Есть два способа сделать это:

  • Неявно через объявленный, используя константу sqlite3.PARSE_DECLTYPES.
  • Явно через имя столбца, используя константу sqlite3.PARSE_COLNAMES.

Оба способа описаны в разделе "Сопутствующие функции и константы модуля".

Следующий пример иллюстрирует оба подхода.

import sqlite3

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

    def __repr__(self):
        return "(%f;%f)" % (self.x, self.y)

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

def convert_point(s):
    x, y = list(map(float, s.split(b";")))
    return Point(x, y)

# регистрируем адаптер
sqlite3.register_adapter(Point, adapt_point)

# регистрируем конвертер
sqlite3.register_converter("point", convert_point)

p = Point(4.0, -3.2)

#########################
# 1) Использование объявленных типов
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.cursor()
cur.execute("create table test(p point)")

cur.execute("insert into test(p) values (?)", (p,))
cur.execute("select p from test")
print("with declared types:", cur.fetchone()[0])
cur.close()
con.close()

#######################
# 1) Использование имен столбцов
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
cur = con.cursor()
cur.execute("create table test(p)")

cur.execute("insert into test(p) values (?)", (p,))
cur.execute('select p as "p [point]" from test')
print("with column names:", cur.fetchone()[0])
cur.close()
con.close()