Как стать автором
Обновить

Комментарии 54

Добавил в закладки. Жду продолжения :)
покрытие кода тестами 100% (с августа 2009)
— причем это не просто покрытие тестами, а 100% branch coverage и 100 MC/DC покрытие, и вообще цифры покрытия тут совсем не главные, их можно было гораздо меньшими усилиями достичь, чем в sqlite это сделано.

Ни в каком другом open-source проекте такой помешанности на тестах не встречал. В sqlite кода тестов в 1000+ раз больше, чем собственно кода проекта, даже с учетом того, что многие тесты написаны на более высокоуровневом Tcl. Всем рекомендую почитать www.sqlite.org/testing.html — душераздирающее чтиво :)
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Тагоряне. Цивилизация гипертрофированной предусмотрительности. Три четверти всех мощностей направлено у них на изучение вредных последствий, каковые могут проистечь из открытия, изобретения, нового технологического процесса и так далее. Эта цивилизация кажется нам странной только потому, что мы не способны понять, насколько это интересно — предотвращать вредные последствия, какую массу интеллектуального и эмоционального наслаждения это дает. Тормозить прогресс так же увлекательно, как и творить его, — все зависит от исходной установки и от воспитания. В результате транспорт у них только общественный, авиации никакой, зато прекрасно развита проводная связь. © Аркадий и Борис Стругацкие. Волны гасят ветер
Про WAL очень даже интересно было бы почитать. Спасибо за статью.
В реализации WAL есть ошибки, пока не признанные разработчиком. В частности, иногда он растёт больше заданных лимитов размера.
SQlite позволяет занести в этот столбец значения любого типа (999, «abc», «123», 678.525).
Если вставляемое значение — не целое, то SQlite пытается привести его к целому.

какой кошмар…

много встроенных функций
по ссылке 40 функций, включая перегруженные варианты. Это хорошо или необычно?

В чем кошмар такого подхода с типами?
По поводу функций, в принципе данного более чем достаточно в повседневной жизни. Если есть необходимость в какой-то специфичной, то можно сделать легко и просто свою функцию, зарегистрировать ее и вызывать уже в SQL запросах, таким образом наращивать функциональность можно столько сколько необходимо.
Например можно реализовать сортировку сложных структур хранящихся в BLOB полях.
Кошмар как минимум в том, что этот подход сразу больно пинает по производительности
На самом деле на уровне SQLite API можно явно указывать, с каким типом работаешь в каждом поле, в этом случае не потребуется не только автоконвертации, но и вообще конвертации чисел в текст в процессе основной работы (не считая, конечно, вывода итогов пользователю). Это если использовать биндинг полей.
Дело не только в конвертации, а еще и в самом хранении таких полей. По сути мы для каждой ячейки должны хранить некий variant — т. е. идентификатор типа и сами данные, которые при вычитывании конвертить.
Что есть ячейка, поле или запись? Для полей тип данных задан в виде семантической информации, но он никак не влияет на способ хранения, только на то как данные будет представлять редактор и компилятор запросов (т.е. к какому типу приводить на автомате). Таким образом любое BLOB поле можно рассматривать как набор бинарных данных, либо как конкретное значение в зависимости от контекста.

Например у себя в одном проекте в поле храню все начиная от просто чисел, заканчивая изображениями. При построении точно знаю какие значения в поле будут находится и уже использую явное указание типа. С тем же успехом можно вычитать бинарные данные и скастовать их в то что нужно.
PS рассуждаю с точки зрения C/C++, в других языках не работал с SQLite.
Да, тип поля, конечно, хранится в БД. Структура файла SQLite хорошо документирована — www.sqlite.org/fileformat.html Типы нужны для 1) конвертации в читабельное состояние при выводе результатов, 2) в SQL-функциях над несовместимыми типами производится конвертация (ну то есть если к строке прибавлять число, то оно конвертируется в число, а не в виде blob'а пристыковывается). Но при операциях над одним типом (наиболее массовые операции — всякие там SUM и прочая арифметика) никакой конвертации, поэтому не ухудшает производительность.
>В чем кошмар такого подхода с типами?

Кошмар не кошмар, но вызывает иногда трудно диагностируемые глюки. Например, в редакторе БД вставляешь значение, а оно записывается не как 1, а как «1» и потом выборка Where someRow=1 возвращает тебе пустоту.
С записью/чтением никогда не было проблем, работаю через Qt обертку и стараюсь использовать prepared statements.
Бывает поля делаю с типом BLOB (читай не типизированные), тогда где необходимо явное приведение типа использую уже CAST.
Работаю с SQLite больше 7 лет, никогда с таким не сталкивался. Наверняка это особенность конкретного редактора БД, а не собственно SQLite.
>В чем кошмар такого подхода с типами?
Сконвертировал/симпортил кривой excel файл и получи на выходи черт пойми какие результаты запросов (все ведь проглотится). Вы в курсе, какие выкрутасы, например, PHP вытворяет при сравнении переменных? Явное, оно, как известно, лучше неявного.
>> по ссылке 40 функций, включая перегруженные варианты. Это хорошо или необычно?

Это в особенности. Стандарта на функции в SQL, как понимаю, не существует.
НЛО прилетело и опубликовало эту надпись здесь
Видимо не для «начинающих программистов в принципе», но для новичка конкретно в SQLite. Т.е., для тех, кто имеет опыт разработки, но без использования SQLite.
Именно. Исправил в статье.
В 2000ом году в качестве халтурки написал биллинг для АТС на 10тыс абонентов, всё это было на Linux, интерфейс через CGI. Тогда использовал Interbase 4 который мог работать без сервера, просто линуешься с библиотекой и она сама открывает файл, ну прямо в точности как SQLlite сегодня. Единственное большое отличие, Interbase реализовывал изоляции транзакций и позволял нескольким процессам писать, использовались средства IPC для синхронизации между несколькими процессами работающими с одной и той же БД, сервера же выделенного при том нет.
Кстати, если вся мощь SQL не особо нужна, а просто ключ-значение, то можно использовать Berkeley DB, который позволяет несколько писателей одновременно, тоже кросс платформенный, на C.
Угу, только Berkeley DB для коммерческого использования нужно покупать. Что как-то не айс для хранения простых «ключ-значение».
НЛО прилетело и опубликовало эту надпись здесь
Спасибо. Как раз для меня статья)
b) можно без труда организовать БД в памяти (это очень удобно и чуть позже расскажу подробнее);

Вот про это хотелось бы почитать.
Неоднократно приходилось использовать SQLite. Всегда оставался доволен. Правда возникали проблемы с синтаксисом команд, он был несколько отличен от привычного мне MySQL, но решения быстро находились. К сожалению, это было давно и конкретные примеры привести не смогу.
Использовал SQLite в одном своем проекте, напоролся на неприятную вещь. Мне приходилось писать в базу часто и маленькими порциями, происходило все это на панельном PC у которого в качестве диска использовалась Compact Flash, так вот по истечении некоторого времени работы приложения (примерно месяц) слетала файловая система, я достаточно много времени потратил на поиск проблемы, и до сих пор на 100% не уверен что я ее нашел, но после того как нашел описанное ниже и устранил приложение работает уже около полу года, так вот, у Sqlite по умолчанию включено ведение журнала, и журнал этот ведется следующим образом — перед началом транзакции создается файл журнала, производится запись в базу, журнал удаляется, и так при каждой транзакции, у меня это происходило где-то раз в секунду. Как известно для удаления файл просто помечается в таблице размещения что он удален, то-есть производилась операция записи в одно и тоже самое место. На обыкновенном HDD такое поведение не вызвало бы никаких проблем, но на флеше это приводило к порче носителя(колличество циклов записи флеш памяти — 10е6 раз), когда вы пишете на нее данные она пишется циклично и одна и таже ячейка не модифицируется постоянно, в моем же случае происходила именно модификация одной и той же самой ячейки, что приводило к сбою. Вот так вот коварно…
«устранил»
Что именно вы сделали, подскажите? Отключили журнал? А бэкап прикрутили потом? Или уже был?
Отключил ведение журнала и написал скрипты востановления базы, база Sqlite, если в ней возникли проблемы, может быть считана до того места где эта проблема возникла, меня это устраивало. Бекапить в поле некуда. :)
> база Sqlite, если в ней возникли проблемы, может быть считана до того места где эта проблема возникла,

Можете чуть подробнее об этом рассказать? очень интересно.
Если SQLite база сбоит (обычные команды открытия/чтения базы дают ошибку SQLITE_CORRUPT), то часто все-равно можно сделать «sqlite .dump» через консоль, получить все данные (в виде команд insert) до сбойного места. Ну как в MySQL в случае myisam можно частично восстановить табличку после сбоя.
Опередили:)
Можно было не отключать ведение журнала, а вести его в памяти:

PRAGMA journal_mode = MEMORY

И тем самым сохранить возможность делать ROLLBACK.

Спасибо, попробую.
sqlite — безусловно хорошая штука. Пользовался ей в нескольких проектах, единственное что огорчает — отсутствие враппера для С++ в стандартной поставке, в результате их пишут все кому не лень (да и чего скрывать — я тоже свой писал, т.к. не нашел подходящего под свои требования). А без враппера юзать sqlite не очень удобно, в плюсах разумеется.
Хороших врапперов мало, но я не так давно стал использовать Poco::Data и остался очень доволен. Все в стиле с++, очень хорошо ложится в проект.
в контексте SQLITE меня убивают вещи типа «sqlite-server»
люди СПЕЦИАЛЬНО делали встраиваимою базу данных
так надо поверх нее сделать клиент сервера…
причем с завидным упорством…

p.s. а уж в где только SQLITE не используется, даже вон в Adobe Light Room
Ну а что удивительного? Есть отлично работающая база и возникает задача одновременного доступа из нескольких приложений.

И не хочется все бросить и ставить Oracle, если можно придумать как обойтись SQLite ;-)
ага, и как результат — получим недо mySQL/etc
у этого проекта есть идея — быть локальной базой
нужны сетевые — их есть
Дык мускуль на что? :-)
На самом деле SQLite3 и так позволяет нормальный параллельный доступ из разных процессов и из разных потоков к одним и тем же БД, не требуется ничего наворачивать сверху, SQLite сам разбирается со всеми блокировками, кэшами и т.п. В частности, это очень активно используется в Eserv (отечественный почтовый и веб сервер), начиная с 4й версии (индексы писем и пр.).
Наиглавнейшее достоинство SQLite — переносимость. За это ей можно было бы простить все что угодно. А уж то что она сама по себе неплоха и вовсе замечательно.
Мне вот единственное что мешает — отсутствие редактируемых вьюх.
Я как-то редко использую view. Может и зря. А зачем их редактировать?
Скажем, в моем случае:
1. Есть БД. Делается запрос со всякими джойнами и кладется в табличное представление.
2. В табличном представлении пользователь что-то меняет.
3. Апдейтится БД.

Через View пункт 3 делается с пол тычка. Без этого же приходится писать промежуточную модель данных с таблицей и расшифровкой каждого ее столбца — из какой таблицы/столбца БД взяты эти данные. Иначе непонятно, куда записывать изменения.
То есть базы которые update view сразу занесут сами в несколько таблиц? Не знал. Круто.
Как вариант, можно использовать INSTEAD OF триггер для изменения/удаления/вставки и самому реализовать необходимую логику. (применимо для MS/Oracle/PostgreSQL)
Получил очень неприятный опыт. Как оказалось, SQLite некорректно обрабатывает запросы с выборками дат. Выяснилось в самый последний момент.
Рекомендую хранить даты SQLite в строковом формате «YYYY-MM-DD hh:mm:ss», это избавляет от проблем сортировки и выборки.
Обычно даты хранят в UNIX-формате (число секунд) в поясе UTC. Зачем хранить в строковом виде?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории