Базы данных
С языком идут два драйвера: PostgreSQL по проводу и чтение файла SQLite. Оба написаны на самом flang, оба проверяются примерами без всякой базы.
Кто носит байты
Программа на flang не открывает ни сокетов, ни файлов. Она возвращает план — описание действия: «открой соединение туда», «отправь эти байты», «прочитай ответ». Описанное исполняет тот, кто запустил план.
Поэтому сборка сообщений и разбор ответов остаются обычными тотальными функциями, а flang check не требует сервера.
PostgreSQL: подключиться и спросить
| файл | что внутри | строк | функций | примеров |
|---|---|---|---|---|
flang/stdlib/wire.flang | октеты, числа в сетевом порядке, строки с нулём на конце, нарезка потока | 1098 | 34 | 77 |
flang/stdlib/postgres.flang | протокол версии 3.0: сообщения клиента собираются, ответы сервера разбираются | 1871 | 67 | 126 |
examples/db/postgres-plan.flang | весь разговор из пяти шагов | 554 | 55 |
Простой запрос собирается так — взято из дерева знак в знак:
тотальная функция «Простой запрос»
принимает запрос: строка
возвращает «Печать»
обеспечивает «простой запрос едет буквой Q, а вместе с длиной и завершающим нулём весит на шесть байтов больше самого запроса» разбор результат
случай вариант «Напечатано» с текст как текст
то (текст начинается с "Q") и притом ((«Байтов в тексте» от текст) равен (6 плюс («Байтов в тексте» от запрос)))
случай вариант «Число непечатаемо» с значение как названо
то названо равен (5 плюс («Байтов в тексте» от запрос))
обеспечивает «простой запрос едет кадром Q со строкой с нулём» (не («Четыре октета печатаются» от (4 плюс («Байтов в тексте» от («Строка с нулём» от запрос))))) или (результат равен (вариант «Напечатано» с текст равным (соединить (соединить "Q" с («Четыре октета» от (4 плюс («Байтов в тексте» от («Строка с нулём» от запрос))))) с («Строка с нулём» от запрос))))
обеспечивает «непечатаемая длина простого запроса названа числом» («Четыре октета печатаются» от (4 плюс («Байтов в тексте» от («Строка с нулём» от запрос)))) или (результат равен (вариант «Число непечатаемо» с значение равным (4 плюс («Байтов в тексте» от («Строка с нулём» от запрос)))))
пример «запрос едет буквой Q»
дано запрос равно "a"
ожидается вариант «Напечатано» с текст равным "Q\u0000\u0000\u0000\u0006a\u0000"
«Кадр» от "Q" и («Строка с нулём» от запрос)
Взято из дерева целиком, знак в знак — flang/stdlib/postgres.flang.
Проверка и примеры базы не требуют:
$ flang check flang/stdlib/postgres.flang
$ flang test flang/stdlib/postgres.flang
Самому разговору живой сервер нужен:
$ flang io examples/db/postgres-plan.flang | python3 -c \
"import sys,json; print(json.load(sys.stdin)['result'])"
1 пуск: | | | in_hot_standby=off … server_version=17.10 server_encoding=UTF8
2 создание: INSERT 0 1| | |
3 вставка с параметрами: INSERT 0 1| | |
4 выборка: SELECT 2| | 1 Мир ; 2 dva|
5 отказ: | ERROR 42703 column "netakoykolonki" does not exist| |
Пять шагов: пуск с паролем открытым текстом, создание, вставка с параметрами ($1, $2), выборка и нарочно кривой запрос, на который сервер отвечает своим кодом. Кириллица ездит в обе стороны. Без трубы команда печатает один объект JSON: в поле result — отчёт выше, в log — каждое поручение и каждый ответ, байт за байтом.
План подключается к 127.0.0.1:55434 пользователем flang, база postgres. Адрес, порт, пользователь и пароль стоят в плане литералами: план не принимает аргументов, а программа не видит окружения. Меняются они правкой функций в начале плана.
PostgreSQL: что работает, а что нет
trust и пароль открытым текстом | работает |
md5, scram-sha-256 | нет: HMAC и PBKDF2 в библиотеке нет. План продолжает читать и ждёт |
| TLS | нет. Разговор идёт открытым текстом — годится для базы на той же машине |
типы колонок из RowDescription | берётся только число колонок. Номер типа колонки передаёте сами |
| пустое значение (null) | не разбирается: его длина — минус один, и разбор просит 4 294 967 295 октетов |
| длина отправляемого сообщения | все четыре октета длины должны быть меньше 128; запрос добивается пробелами, 200 в запасе. Значение параметра — не больше 127 байт |
| один проход разбора | не больше 1000 сообщений |
| испорченный поток | останавливает разбор отдельным ответом, а не молча |
SQLite: прочитать файл
flang/stdlib/sqlite.flang читает базу SQLite 3 как список октетов: образ файла приходит одним поручением Прочитать октеты из файла. Ни сервера, ни провода.
Сделайте образец сторонней sqlite3 и прочитайте его обратно:
$ python3 -c "import sqlite3,os; d='/srv/tmp/sqlite-obrazec'; os.makedirs(d,exist_ok=True); \
c=sqlite3.connect(d+'/proba.db'); c.execute('create table люди(имя text, лет integer)'); \
c.executemany('insert into люди values (?,?)',[('Аня',31),('Боря',44),('Вера',7)]); c.commit()"
$ flang io examples/db/sqlite-read.flang | python3 -c \
"import sys,json; print(json.load(sys.stdin)['result'])"
магия SQLite: да
размер страницы: 4096
страниц: 2
октетов в файле: 8192
таблицы: люди
корень таблицы люди: 2
SQL: CREATE TABLE люди(имя text, лет integer)
строк: 3
1 | Аня | 31
2 | Боря | 44
3 | Вера | 7
План — examples/db/sqlite-read.flang; путь к файлу и имя таблицы стоят в нём двумя однострочными функциями: «Откуда» и «Какая таблица».
SQLite: что читается, а что нет
| заголовок | магия, размер страницы, число страниц |
страница-схема sqlite_master | имена таблиц, их корневые страницы, их SQL |
| лист b-дерева таблицы | указатели на ячейки, длина нагрузки, номер строки, сама нагрузка |
| запись (record) | ноль, целые всех шести ширин, нули и единицы серийных типов 8 и 9, текст через UTF-8, двоичное |
| вещественные числа (серийный тип 7) | восемь октетов отдаются как есть, вариантом «Дробное» |
| запись в базу | нет. Читающий драйвер — половина, которую можно проверить целиком, не ломая чужой файл |
| внутренние страницы b-дерева и переполнение | нет. Они начинаются на таблице крупнее одной страницы; возвращается пусто, а не подделка. «Вид страницы» отдаёт 13 у листа таблицы и 5 у внутренней |
| индексы (виды страниц 2 и 10) | нет: они не строки таблицы |
Куда дальше
- Процессы, надзор, распределённость — кто держит соединение, пока идёт работа.
- Встраивание flang — как драйвер попадает в программу на вашем языке.