SQLite
SQLite - это компактная встраиваемая реляционная база данных. Исходный код библиотеки общедоступен. В 2005 году проект получил награду Google-O'Reilly Open Source Awards.
Дизайн
SQLite не использует парадигму клиент-сервер, то есть движок SQLite не является отдельно работающим процессом, с которым взаимодействует программа, а предоставляет библиотеку, с которой программа компонуется и движок становится составной частью программы. Таким образом, в качестве протокола обмена используются вызовы функций (API) библиотеки SQLite. Такой подход уменьшает накладные расходы, время отклика и упрощает программу. SQLite хранит всю базу данных (включая определения, таблицы, индексы и данные) в единственном стандартном файле на том компьютере, на котором исполняется программа. Простота реализации достигается за счёт того, что перед началом исполнения транзакции записи весь файл, хранящий базу данных, блокируется; ACID-функции достигаются в том числе за счёт создания файла журнала.
Несколько процессов или потоков могут одновременно без каких-либо проблем читать данные из одной базы. Запись в базу можно осуществить только в том случае, если никаких других запросов в данный момент не обслуживается; в противном случае попытка записи оканчивается неудачей, и в программу возвращается код ошибки. Другим вариантом развития событий является автоматическое повторение попыток записи в течение заданного интервала времени.
Благодаря архитектуре движка возможно использовать SQLite как на встраиваемых системах, так и на выделенных машинах с гигабайтными массивами данных.
Типы данных
SQLite поддерживает динамическое типизирование данных. Возможные типы полей: INTEGER, REAL, TEXT, BLOB.
Ограничения
Старые версии SQLite были спроектированы без каких-либо ограничений, единственным условием было то, чтобы база данных умещалась в памяти, в которой все вычисления производились при помощи 32-разрядных целых чисел. Это создавало определённые проблемы. Из-за того, что верхние пределы не были определены и соответственно должным образом протестированы, часто обнаруживались ошибки при использовании SQLite в достаточно экстремальных условиях. Поэтому в новых версиях SQLite были введены пределы, которые теперь проверяются вместе с общим набором тестов.
Во время компиляции библиотеки SQLite устанавливаются следующие ограничения, которые можно, при острой необходимости, увеличивать:
На текущий момент только значение SQLITE_MAX_PAGE_SIZE не может быть больше заданного по умолчанию. Таким образом, не изменяя SQLITE_MAX_PAGE_COUNT, можно сказать, что максимальный размер файла базы данных составляет примерно 32 ТБ.
Использование
Сама библиотека SQLite написана на C; существует большое количество привязок к другим языкам программирования, в том числе Delphi, C++, Java, C#, VB.NET, Python, Perl, PHP, PureBasic, Tcl (средства для работы с Tcl включены в комплект поставки SQLite), Ruby, Haskell, Scheme, Smalltalk, Lua и Parser, а также ко многим другим.
Простота и удобство встраивания SQLite привели к тому, что библиотека используется в браузерах, музыкальных плеерах и многих других программах.
SQLite используют:
- Adobe Integrated Runtime — среда для запуска приложений (частично);
- Gears;
- Autoit;
- Фреймворк Qt;
- Платформа XUL на движке Gecko 1.9+, XULRunner 1.9+ и, потенциально, все приложения, основанные на этой платформе, в том числе:
- Mozilla Firefox (начиная с версии 3.0)
- Mozilla Thunderbird (начиная с версии 3.0)
- Songbird
- SQLite Manager.
- Skype;
- Некоторые модели GPS-навигаторов Garmin
- Android API
Файловое строение SQLite
Вся база данных хранится в одном файле на диске под названием "main database file". Во время транзакций, SQLite хранит дополнительную информацию во втором файле: журнал отката (rollback journal), либо, если база работает в режиме WAL, лог-файл с информацией о записях. Если приложение или компьютер отключился до окончания транзакции, то данные файлы называются "hot journal" или "hot WAL file" и содержат необходимую информацию для восстановления базы в согласованное состояние.
Страницы
Основной файл базы состоит из одной или нескольких страниц. Все страницы в одной базе имеют одинаковый размер, который может быть от 512 до 65536 байт. Размер страницы для файла базы определяется целым 2-ух байтовым числом со смещением 16 байт от начала файла базы данных.
ОС Tizen также поддерживает SQLite.
В предлагаемом примере мы разработаем приложение, в котором данные по истории технологий шифрования будут храниться в базе данных SQLite.
Создадим проект SQLite.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>CSS3 Basic User Interface</title> <meta name="viewport" content="width=device-width, minimum-scale=1.0" /> <style> *{ margin: 0; padding: 0; } body{ padding: 15px; } table{ width: 100%; margin-bottom: 20px; border-collapse: collapse; border-spacing: 0; font-size: .9em; } table caption{ padding: 5px; font-size: 1.2em; } table th, table td{ padding: 10px 5px; } table th{ background-color: #333; color: #fff; box-shadow: inset 1px 1px 0 rgba(255,255,255,.7); } table td{ box-shadow: inset -1px -1px 5px rgba(0,0,0,.7); } table thead tr th{ border-radius: 5px; } table tbody tr:first-child th:first-child{ border-radius: 5px 0 0 0; } table tbody tr:last-child th:first-child{ border-radius: 0 0 0 5px; } table tbody tr:first-child td:last-child{ border-radius: 0 5px 0 0; } table tbody tr:last-child td:last-child{ border-radius: 0 0 5px 0; } .button_wrap{ margin: 0 auto; } .button_wrap button{ margin: 0 .3em; } </style> <script> var db; //database varsion setting var version = 1.0; //database name setting var dbName = "tizendb"; //database display name setting var dbDisplayName = "tizen_test_db"; //database size setting var dbSize = 2 * 1024 * 1024; function selectDB() { if (window.openDatabase) { //openDatabase(name, version, displayname, estimatedsize, callback); db = openDatabase(dbName, version, dbDisplayName, dbSize); dropTable(db); createTable(db); //inserting data in table insertData(db, "period01", "Господство моноалфавитных шифров (основной принцип — замена алфавита исходного текста другим алфавитом через замену букв другими буквами или символами)", "Три тысячи лет до н.э."); insertData(db, "period02", "Введение в обиход полиалфавитных шифров", "С IX века на Ближнем Востоке (Ал-Кинди) и с XV века в Европе (Леон Баттиста Альберти) — до начала XX века"); insertData(db, "period03", "Внедрение электромеханических устройств в работу шифровальщиков. При этом продолжалось использование полиалфавитных шифров", "С начала и до середины XX века"); insertData(db, "period04", "Переход к математической криптографии", "С середины до 70-х годов XX века"); insertData(db, "period05", "Криптография с открытым ключом", "Современный период развития криптографии (с конца 1970-х годов по настоящее время)"); dataView(db); } else { alert("Web SQL Database not supported in this browser"); } } //reads and displays values from the 'places' table function dataView(db) { var html = document.getElementById("tbody01"); var ddlHtml = document.getElementById("ddlTitle"); html.innerHTML = ""; ddlHtml.innerHTML = ""; db.transaction(function (t) { t.executeSql("SELECT * FROM Cryptography_tbl", [], function (tran, r) { ddlHtml.innerHTML = "<option value='all'>all</option>"; for (var i = 0; i < r.rows.length; i++) { var id = r.rows.item(i).id; var title = r.rows.item(i).title; var content = r.rows.item(i).content; var insertday = r.rows.item(i).insertDay; //data list rendering if (html) { html.innerHTML += "<tr><td>" + id + "</td><td>" + title + "</td><td>" + content + "</td><td>" + insertday + "</td></tr>"; } //select box rendering if (ddlHtml) { ddlHtml.innerHTML += "<option value=" + id + ">" + title + "</option>"; } } }, function (t, e) { alert("Error:" + e.message); } ); }); } // create table function createTable(db) { db.transaction(function (t) { t.executeSql("CREATE TABLE Cryptography_tbl (id INTEGER PRIMARY KEY, title TEXT, content TEXT, insertDay TEXT)", []); }); } //inserting data in table function insertData(db, title, context, insertDay) { db.transaction(function (e) { //var day = new Date(); e.executeSql("INSERT INTO Cryptography_tbl(title, content, insertDay) VALUES (?, ?, ?)", [title, context, insertDay], onSuccess, onError); }); } function onSuccess(e) { } function onError(e) { } // drop table function dropTable(db) { db.transaction(function (e) { e.executeSql("DROP TABLE Cryptography_tbl"); }); } //Select the data conditions function dataChange(value) { if (value != "all") { var html = document.getElementById("tbody01"); html.innerHTML = ""; db.transaction(function (t) { t.executeSql("SELECT * FROM Cryptography_tbl WHERE id=?", [value], function (tran, r) { for (var i = 0; i < r.rows.length; i++) { var id = r.rows.item(i).id; var title = r.rows.item(i).title; var content = r.rows.item(i).content; var insertday = r.rows.item(i).insertDay; if (html) { html.innerHTML += "<tr><td>" + id + "</td><td>" + title + "</td><td>" + content + "</td><td>" + insertday + "</td></tr>"; } } }, function (t, e) { alert("Error:" + e.message); } ); }); } else { dataView(db); } } window.onload = function () { selectDB(); }; </script> </head> <body> <div style="float: right;"> <select id="ddlTitle" onchange="dataChange(this.value);"> </select> </div> <table> <caption> <h2>Основные этапы развития криптографии</h2> </caption> <thead> <tr> <th>id</th> <th>Период</th> <th>Характеристика</th> <th>Дата</th> </tr> </thead> <tbody id="tbody01"> </tbody> </table> </body> </html>