SQLite — быстрый старт

В этой статье мы напишем простую программу с использованием библиотеки SQLite. Программа создаст базу данных, запишет туда информацию, а потом выведет эту информацию на экран.

1. Создание нового проекта

Для работы с таблицей мы будем виджеты GTK+, поэтому запустите CodeBlocks и выполните «Файл — Создать — Проект — GTK+ project». Готовый проект вы можете скачать в конце этой статьи.

Установите параметры проекта. Меню «Проект — Свойства — Цели сборки». Поставьте выделенные параметры.

Запустите приложение для проверки.

Библиотека GTK+ работает. Теперь убедитесь, что библиотека SQLite подключена к CodeBlocks. Об этом подробно написано здесь.

2. Подключение GtkListStore для вывода таблицы

В GTK+ для работы со сложными данными используется GtkTreeModel — набор функций для хранения и отображения данных.
Существует две модели хранения GtkListStore и GtkTreeStore и один виджет отображения GtkTreeView, который поддерживает обе модели хранения.

Для работы с таблицами нужно сделать запрос к БД и поместить результат в структуру GtkListStore. Виджет GtkTreeView отобразит данные в виде таблицы.

Для работы с таблицей в GTK+ нужно:

  1. Создать буфер GtkListStore.
  2. Добавить строки в буфер.
  3. Создать таблицу GtkTreeView.
  4. Добавить столбцы в таблицу.

Для обращения к таблице используется:

  • Итератор GtkTreeIter — текущая строка.
  • Колонка GtkTreeViewColumn — текущий столбец.
  • Рендер GtkCellRenderer — текущая ячейка.

Запускаем Glade и готовим виджет, для этого.

  1. Создаем буфер liststore1 для модели таблицы,
  2. Создаем виджет дерева treeview1.
  3. Указываем для этого виджета буфер liststore1.

Сохраняем интерфейс в файл main.glade. Виджет готов, теперь его надо настроить: указать столбцы и формат ячеек.

3. Настройка виджета GtkTreeView в Glade

У нас сейчас пустое окно, в котором есть дерево treeview1 и буфер liststore1. Нажимаем на иконку Edit.

В редакторе виджета «Дерево» столбцы настраиваются на вкладке “Основные”, а ячейки — на вкладке “Иерархия”. Сначала добавим три столбца:

  • guint1
  • gcharray1
  • guin2

Теперь настроим ячейки:

  • Номер
  • Фамилия
  • Оклад

Всё, интерфейс готов. Теперь можно писать обращение к базе данных.

4. Создание базы данных SQLite

Для подключения к БД SQLite используется команда sqlite3_open(«b1.db», &db). В этой строчке открывается база данных b1.db, если ее нет, то она создается.

В качестве примера возьмем таблицу «Сотрудники», в которой зададим поля:

  • N
  • Фамилия
  • Оклад

Теперь составляем SQL-запрос, в котором создаем таблицу «Сотрудники» и задаем значения полей. Начинается запрос с удаления таблицы «Сотрудники», если она есть. Это для того, чтобы мы могли запускать программу несколько раз.

// Запись в БД
int SaveDB()
{
    char* SQL1 = "DROP TABLE IF EXISTS Сотрудники; \
            CREATE TABLE Сотрудники(N,Фамилия,Оклад); \
            INSERT INTO Сотрудники VALUES(1,'Иванов',20000);  \
            INSERT INTO Сотрудники VALUES(2,'Петров',25000);  \
            INSERT INTO Сотрудники VALUES(3,'Сидоров',30000);  \
            ";


     if (sqlite3_exec(db, SQL1, 0, 0, &err))
    {
        sprintf(str, "Ошибка выполнения SQL-запроса: %sn", err);
        sqlite3_free(err);
        return 2;
    }
    return 0;
}

 

5. Загрузка данных в буфер виджета GtkTreeView

Когда мы подключились к баз данных, мы можем загрузить строки БД в буфер виджета GtkTreeView. Сам буфер мы задаем строчкой:

GtkListStore *buffer; // Буфер таблицы

Загрузку данных выполняет следующий код:

   // Цикл по SQL-запросу и запись в буфер таблицы
    while((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        gtk_list_store_append (buffer, &iter);
        gtk_list_store_set (buffer, &iter,
                       C_NUM, sqlite3_column_int(stmt, C_NUM),
                       C_NAME, sqlite3_column_text(stmt, C_NAME),
                       C_OKLAD, (guint) sqlite3_column_int(stmt, C_OKLAD),
                      -1);
    }

Здесь мы в цикле перебираем строки запроса и заполняем ячейки таблицы значениями полей из базы данных.

6. Итоговая программа

Остальные шаги по выводу таблицы на экран достаточно стандартны. Подключаем интерфейс main.glade и выводим на экран основное окно. Вот код целиком.

/****************************************
Пример использования SQLite и GtkTreeView
*****************************************/
#include <stdlib.h>
#include <gtk/gtk.h>
#include <sqlite3.h>

GtkWidget   *window1;
GtkBuilder  *builder1;

sqlite3 *db;    // хэндл БД

// Структуры данных для виджета
GtkListStore        *buffer;    // Буфер таблицы
GtkTreeView         *table;     // Таблица
GtkTreeViewColumn   *column;    // Отображаемая колонка
GtkTreeIter         iter;       // Итератор таблицы (текущая строка)
GtkCellRenderer     *renderer;  // Рендер таблицы (текущая ячейка)

// Обозначения полей
enum
{
    C_NUM, C_NAME, C_OKLAD
};

// Структуры данных для базы данных
sqlite3_stmt* stmt; // строка запроса к БД
char *err = 0;
int rc = 0;


int ShowGladeError()
{
    GtkWidget *dialog;

    dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
                                 GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
                                 "Не найден файл\n main.glade");

    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);

    return 0;
}


char str[1000];
int lenstr=0;

// Открываем БД
void StartDB()
{
    if( sqlite3_open("b1.db", &db))
    {
        sprintf(str, "Ошибка открытия БД: %s\n", sqlite3_errmsg(db));
    }
}

void EndDB()
{
    sqlite3_close(db);
}

// Запись в БД
int SaveDB()
{
    char* SQL1 = "DROP TABLE IF EXISTS Сотрудники; \
            CREATE TABLE Сотрудники(N,Фамилия,Оклад); \
            INSERT INTO Сотрудники VALUES(1,'Иванов',20000);  \
            INSERT INTO Сотрудники VALUES(2,'Петров',25000);  \
            INSERT INTO Сотрудники VALUES(3,'Сидоров',30000);  \
            ";


     if (sqlite3_exec(db, SQL1, 0, 0, &err))
    {
        sprintf(str, "Ошибка выполнения SQL-запроса: %sn", err);
        sqlite3_free(err);
        return 2;
    }
    return 0;
}


// Загрузка таблицы из БД в буфер виджета
int LoadDB()
{
    char* SQL2 = "SELECT N, Фамилия, Оклад FROM Сотрудники;";
    // Готовим SQL-запрос к БД
    if(sqlite3_prepare_v2(db, SQL2, -1, &stmt, NULL) != SQLITE_OK)
    {
        sprintf(str, "Ошибка подготовки SQL-запроса: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return 3;
    }

    // Цикл по SQL-запросу и запись в буфер таблицы
    while((rc = sqlite3_step(stmt)) == SQLITE_ROW)
    {
        gtk_list_store_append (buffer, &iter);
        gtk_list_store_set (buffer, &iter,
                       C_NUM, sqlite3_column_int(stmt, C_NUM),
                       C_NAME, sqlite3_column_text(stmt, C_NAME),
                       C_OKLAD, (guint) sqlite3_column_int(stmt, C_OKLAD),
                      -1);
    }
    if(rc != SQLITE_DONE)
    {
        sprintf(str, "Ошибка выполнения SQL-запроса: %s\n", sqlite3_errmsg(db));
        sqlite3_finalize(stmt);
        return 4;
    }

    // 5. Освобождаем строку запроса
    sqlite3_finalize(stmt);

    return 0;
}

void ShowError ()
{
    GtkWidget *dialog = NULL;

    dialog = gtk_message_dialog_new (GTK_WINDOW (window1), GTK_DIALOG_MODAL,
                                     GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, str);
    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
    gtk_dialog_run (GTK_DIALOG (dialog));
    gtk_widget_destroy (dialog);
}

int ShowMainWindow()
{
	builder1 = gtk_builder_new ();
	if (gtk_builder_add_from_file (builder1, "main.glade", NULL))
	{
        window1 = GTK_WIDGET(gtk_builder_get_object(builder1, "window1"));
        buffer =  GTK_LIST_STORE(gtk_builder_get_object(builder1, "liststore1"));
        table =  GTK_TREE_VIEW(gtk_builder_get_object(builder1, "treeview1"));



        gtk_window_set_default_size (GTK_WINDOW (window1), 500, 300);
        gtk_window_set_position(GTK_WINDOW(window1), GTK_WIN_POS_CENTER);

	    gtk_builder_connect_signals (builder1, NULL);
        g_signal_connect(G_OBJECT(window1), "destroy", G_CALLBACK(gtk_main_quit), NULL);

        SaveDB();
        if(LoadDB())
        {
            ShowError();
        }


        gtk_widget_show (window1);

        return TRUE;
	}
    else
	{
	    return FALSE;
	}
}


int main (int argc, char *argv[])
{
    gtk_init (&argc, &argv);
    StartDB();
    if (ShowMainWindow ())
    {
       gtk_main ();
       EndDB();
       return 0;
    }
    else
    {
       ShowGladeError();
       EndDB();
       return 1;
    }
}

В результате мы получаем вывод таблицы из базы данных на экран.

С помощью SQLite Studio можно подключиться к этой БД и увидеть, что все данные отражаются правильно.

Полностью проект можно скачать здесь

 

 

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.

➤