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>
