Spec-Zone.ru › SQLite

Примечание редакции: В этом документе описана SQLite версии 2, поддержка которой была прекращена, а в 2004 году её заменила SQLite3. Этот документ сохранён как часть исторического наследия SQLite. Современным программистам следует обращаться к более актуальной документации по SQLite, доступной в других разделах этого сайта.

Интерфейс языка C для SQLite версии 2

Библиотека SQLite разработана так, чтобы её было очень легко использовать из программ на C или C++. В этом документе представлен обзор интерфейса программирования на C/C++.

1.0 Основной API

Интерфейс библиотеки SQLite состоит из трёх основных функций, одной непрозрачной структуры данных и нескольких констант, используемых в качестве возвращаемых значений. Основной интерфейс выглядит следующим образом:

typedef struct sqlite sqlite;
#define SQLITE_OK           0   /* Successful result */

sqlite *sqlite_open(const char *dbname, int mode, char **errmsg);

void sqlite_close(sqlite *db);

int sqlite_exec(
  sqlite *db,
  char *sql,
  int (*xCallback)(void*,int,char**,char**),
  void *pArg,
  char **errmsg
);

Для использования SQLite в программах на C или C++ действительно достаточно знать всё перечисленное выше. Доступны и другие функции интерфейса (они описаны ниже), но сначала мы рассмотрим основные функции, показанные выше.

1.1 Открытие базы данных

Используйте функцию sqlite_open, чтобы открыть существующую базу данных SQLite или создать новую. Первый аргумент — имя базы данных. Второй аргумент предназначен для указания того, будет ли база данных использоваться для чтения и записи или только для чтения. Однако в текущей реализации второй аргумент функции sqlite_open игнорируется. Третий аргумент — указатель на указатель строки. Если третий аргумент не равен NULL и при попытке открыть базу данных возникает ошибка, сообщение об ошибке будет записано в память, полученную с помощью malloc(), а *errmsg будет указывать на это сообщение. Вызывающая функция отвечает за освобождение этой памяти после завершения работы с ней.

Имя базы данных SQLite — это имя файла, в котором будет храниться база данных. Если файл не существует, SQLite попытается создать и инициализировать его. Если файл доступен только для чтения (из-за разрешений или потому, что он находится на носителе, доступном только для чтения, например CD-ROM), SQLite откроет базу данных только для чтения. Вся база данных SQL хранится в одном файле на диске. Однако во время выполнения команды SQL могут создаваться дополнительные временные файлы для хранения журнала отката базы данных или временных и промежуточных результатов запроса.

Функция sqlite_open возвращает указатель на непрозрачную структуру sqlite. Этот указатель будет первым аргументом всех последующих вызовов функций SQLite, работающих с той же базой данных. Если открыть базу данных не удаётся по какой-либо причине, возвращается NULL.

1.2 Закрытие базы данных

Чтобы закрыть базу данных SQLite, вызовите функцию sqlite_close, передав ей указатель на структуру sqlite, полученный в результате предыдущего вызова sqlite_open. Если при закрытии базы данных активна транзакция, она откатывается.

1.3 Выполнение инструкций SQL

Функция sqlite_exec используется для обработки инструкций SQL и запросов. Эта функция принимает 5 параметров:

  1. Указатель на структуру sqlite, полученную в результате предыдущего вызова sqlite_open.

  2. Завершающаяся нулевым символом строка, содержащая текст одной или нескольких инструкций SQL и/или запросов для обработки.

  3. Указатель на функцию обратного вызова, которая вызывается для каждой строки результата запроса. Этот аргумент может быть равен NULL; в этом случае функция обратного вызова вызываться не будет.

  4. Указатель, который передаётся в качестве первого аргумента функции обратного вызова.

  5. Указатель на строку ошибки. Сообщения об ошибках записываются в область памяти, полученную с помощью malloc(), и строка ошибки начинает указывать на эту область памяти. Вызывающая функция отвечает за освобождение этой памяти после завершения работы с ней. Этот аргумент может быть равен NULL; в этом случае сообщения об ошибках не передаются вызывающей функции.

Функция обратного вызова используется для получения результатов запроса. Её прототип выглядит следующим образом:

int Callback(void *pArg, int argc, char **argv, char **columnNames){
  return 0;
}

Первый аргумент функции обратного вызова — это просто копия четвёртого аргумента sqlite_exec. Этот параметр можно использовать для передачи произвольной информации из клиентского кода в функцию обратного вызова. Второй аргумент — количество столбцов в результате запроса. Третий аргумент — массив указателей на строки, где каждая строка представляет собой один столбец результата для данной записи. Обратите внимание: значение NULL в базе данных функция обратного вызова представляет как указатель NULL, что существенно отличается от пустой строки. Если i-й параметр — пустая строка, результат будет таким:

argv[i][0] == 0

Но если i-й параметр равен NULL, результат будет таким:

argv[i] == 0

Имена столбцов содержатся в первых argc элементах четвёртого аргумента. Если включена прагма SHOW_DATATYPES (по умолчанию она выключена), следующие argc элементов 4-го аргумента содержат типы данных соответствующих столбцов.

Если для прагмы EMPTY_RESULT_CALLBACKS задано значение ON и результат запроса представляет собой пустой набор, функция обратного вызова вызывается один раз, причём третий параметр (argv) устанавливается в 0. Иными словами:

argv == 0
Второй параметр (argc) и четвёртый параметр (columnNames) по-прежнему действительны и могут использоваться для определения количества и имён столбцов результата, если бы результат был. По умолчанию функция обратного вызова не вызывается, если результирующий набор пуст.

Обычно функция обратного вызова должна возвращать 0. Если функция обратного вызова возвращает ненулевое значение, запрос немедленно прерывается, а sqlite_exec возвращает SQLITE_ABORT.

1.4 Коды ошибок

Функция sqlite_exec обычно возвращает SQLITE_OK. Однако при возникновении ошибки она может вернуть другое значение, указывающее на тип ошибки. Ниже приведён полный список возвращаемых кодов:

#define SQLITE_OK           0   /* Successful result */
#define SQLITE_ERROR        1   /* SQL error or missing database */
#define SQLITE_INTERNAL     2   /* An internal logic error in SQLite */
#define SQLITE_PERM         3   /* Access permission denied */
#define SQLITE_ABORT        4   /* Callback routine requested an abort */
#define SQLITE_BUSY         5   /* The database file is locked */
#define SQLITE_LOCKED       6   /* A table in the database is locked */
#define SQLITE_NOMEM        7   /* A malloc() failed */
#define SQLITE_READONLY     8   /* Attempt to write a readonly database */
#define SQLITE_INTERRUPT    9   /* Operation terminated by sqlite_interrupt() */
#define SQLITE_IOERR       10   /* Some kind of disk I/O error occurred */
#define SQLITE_CORRUPT     11   /* The database disk image is malformed */
#define SQLITE_NOTFOUND    12   /* (Internal Only) Table or record not found */
#define SQLITE_FULL        13   /* Insertion failed because database is full */
#define SQLITE_CANTOPEN    14   /* Unable to open the database file */
#define SQLITE_PROTOCOL    15   /* Database lock protocol error */
#define SQLITE_EMPTY       16   /* (Internal Only) Database table is empty */
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to constraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

Значения этих кодов описаны ниже:

  SQLITE_OK This value is returned if everything worked and there were no errors.  SQLITE_INTERNAL This value indicates that an internal consistency check within the SQLite library failed. This can only happen if there is a bug in the SQLite library. If you ever get an SQLITE_INTERNAL reply from an sqlite_exec call, please report the problem on the SQLite mailing list.  SQLITE_ERROR This return value indicates that there was an error in the SQL that was passed into the sqlite_exec.  SQLITE_PERM This return value says that the access permissions on the database file are such that the file cannot be opened.  SQLITE_ABORT This value is returned if the callback function returns non-zero.  SQLITE_BUSY 
This return code indicates that another program or thread has the database locked. SQLite allows two or more threads to read the database at the same time, but only one thread can have the database open for writing at the same time. Locking in SQLite is on the entire database.  SQLITE_LOCKED This return code is similar to SQLITE_BUSY in that it indicates that the database is locked. But the source of the lock is a recursive call to sqlite_exec. This return can only occur if you attempt to invoke sqlite_exec from within a callback routine of a query from a prior invocation of sqlite_exec. Recursive calls to sqlite_exec are allowed as long as they do not attempt to write the same table.  SQLITE_NOMEM This value is returned if a call to malloc fails.  SQLITE_READONLY This return code indicates that an attempt was made to write to a database file that is opened for reading only.  SQLITE_INTERRUPT This value is returned if a call to sqlite_interrupt interrupts a database operation in progress.  SQLITE_IOERR This value is returned if the operating system informs SQLite that it is unable to perform some disk I/O operation. This could mean that there is no more space left on the disk.  SQLITE_CORRUPT This value is returned if SQLite detects that the database it is working on has become corrupted. Corruption might occur due to a rogue process writing to the database file or it might happen due to a previously undetected logic error in SQLite. This value is also returned if a disk I/O error occurs in such a way that SQLite is forced to leave the database file in a corrupted state. The latter should only happen due to a hardware or operating system malfunction.  SQLITE_FULL This value is returned if an insertion failed because there is no space left on the disk, or the database is too big to hold any more information. The latter case should only occur for databases that are larger than 2GB in size.  SQLITE_CANTOPEN This value is returned if the database file could not be opened for some reason.  SQLITE_PROTOCOL This value is returned if some other process is messing with file locks and has violated the file locking protocol that SQLite uses on its rollback journal files.  SQLITE_SCHEMA When the database is first opened, SQLite reads the database schema into memory and uses that schema to parse new SQL statements. If another process changes the schema, the command currently being processed will abort because the virtual machine code generated assumed the old schema. This is the return code for such cases. Retrying the command usually will clear the problem.  SQLITE_TOOBIG SQLite will not store more than about 1 megabyte of data in a single row of a single table. If you attempt to store more than 1 megabyte in a single row, this is the return code you get.  SQLITE_CONSTRAINT This constant is returned if the SQL statement would have violated a database constraint.  SQLITE_MISMATCH This error occurs when there is an attempt to insert non-integer data into a column labeled INTEGER PRIMARY KEY. For most columns, SQLite ignores the data type and allows any kind of data to be stored. But an INTEGER PRIMARY KEY column is only allowed to store integer data.  SQLITE_MISUSE This error might occur if one or more of the SQLite API routines is used incorrectly. Examples of incorrect usage include calling sqlite_exec after the database has been closed using sqlite_close or calling sqlite_exec with the same database pointer simultaneously from two separate threads.  SQLITE_NOLFS This error means that you have attempted to create or access a database file that is larger than 2GB on a legacy Unix machine that lacks large file support.  SQLITE_AUTH This error indicates that the authorizer callback has disallowed the SQL you are attempting to execute.  SQLITE_ROW This is one of the return codes from the sqlite_step routine which is part of the non-callback API. It indicates that another row of result data is available.  SQLITE_DONE This is one of the return codes from the sqlite_step routine which is part of the non-callback API. It indicates that the SQL statement has been completely executed and the sqlite_finalize routine is ready to be called.   

2.0 Доступ к данным без использования функции обратного вызова

Ранее описанная процедура sqlite_exec была единственным способом извлечения данных из базы данных SQLite. Однако многие программисты сочли неудобным использование функции обратного вызова для получения результатов. Поэтому начиная с SQLite версии 2.7.7 доступен второй интерфейс, не использующий функции обратного вызова.

В новом интерфейсе одна функция sqlite_exec заменена тремя отдельными функциями.

typedef struct sqlite_vm sqlite_vm;

int sqlite_compile(
  sqlite *db,              /* The open database */
  const char *zSql,        /* SQL statement to be compiled */
  const char **pzTail,     /* OUT: uncompiled tail of zSql */
  sqlite_vm **ppVm,        /* OUT: the virtual machine to execute zSql */
  char **pzErrmsg          /* OUT: Error message. */
);

int sqlite_step(
  sqlite_vm *pVm,          /* The virtual machine to execute */
  int *pN,                 /* OUT: Number of columns in result */
  const char ***pazValue,  /* OUT: Column data */
  const char ***pazColName /* OUT: Column names and datatypes */
);

int sqlite_finalize(
  sqlite_vm *pVm,          /* The virtual machine to be finalized */
  char **pzErrMsg          /* OUT: Error message */
);

Предполагается скомпилировать одну инструкцию SQL с помощью sqlite_compile, затем вызывать sqlite_step несколько раз — по одному разу для каждой строки результата, — а после завершения выполнения SQL вызвать sqlite_finalize для очистки.

2.1 Компиляция инструкции SQL в виртуальную машину

Функция sqlite_compile «компилирует» одну инструкцию SQL (указанную вторым параметром) и создаёт виртуальную машину, способную выполнить эту инструкцию. Как и для большинства функций интерфейса, первым параметром должен быть указатель на структуру sqlite, полученную в результате предыдущего вызова sqlite_open.

Указатель на виртуальную машину сохраняется по адресу, переданному в качестве 4-го параметра. Память для виртуальной машины выделяется динамически. Чтобы избежать утечки памяти, вызывающая функция должна вызвать sqlite_finalize для виртуальной машины после завершения работы с ней. Если во время компиляции возникает ошибка, 4-й параметр может быть установлен в NULL.

Если во время компиляции возникает ошибка, сообщение об ошибке записывается в память, полученную с помощью malloc, а 5-й параметр начинает указывать на эту память. Если 5-й параметр равен NULL, сообщение об ошибке не создаётся. Если 5-й параметр не равен NULL, вызывающая функция должна освободить память, содержащую сообщение об ошибке, вызвав sqlite_freemem.

Если 2-й параметр содержит две или более инструкции SQL, компилируется только первая инструкция. (Это отличается от поведения sqlite_exec, которая выполняет все инструкции SQL во входной строке.) 3-й параметр функции sqlite_compile начинает указывать на первый символ после окончания первой инструкции SQL во входных данных. Если 2-й параметр содержит только одну инструкцию SQL, 3-й параметр будет указывать на завершающий символ '\000' в конце 2-го параметра.

В случае успеха sqlite_compile возвращает SQLITE_OK. В противном случае возвращается код ошибки.

2.2 Пошаговое выполнение инструкции SQL

После создания виртуальной машины с помощью sqlite_compile она выполняется одним или несколькими вызовами sqlite_step. Каждый вызов sqlite_step, кроме последнего, возвращает одну строку результата. Количество столбцов в результате сохраняется в целочисленной переменной, на которую указывает 2-й параметр. Указатель, заданный 3-м параметром, начинает указывать на массив указателей на значения столбцов. Указатель, заданный 4-м параметром, начинает указывать на массив указателей на имена столбцов и типы данных. Параметры со 2-го по 4-й функции sqlite_step передают ту же информацию, что и параметры со 2-го по 4-й функции callback при использовании интерфейса sqlite_exec. Однако в случае sqlite_step информация о типах данных столбцов всегда включается в 4-й параметр независимо от того, включена или выключена прагма SHOW_DATATYPES.

Каждый вызов sqlite_step возвращает целочисленный код, указывающий на результат выполнения этого шага. Кодом может быть SQLITE_BUSY, SQLITE_ROW, SQLITE_DONE, SQLITE_ERROR или SQLITE_MISUSE.

Если виртуальная машина не может открыть файл базы данных, поскольку он заблокирован другим потоком или процессом, sqlite_step возвращает SQLITE_BUSY. Вызывающая функция должна выполнить другое действие или ненадолго приостановиться, чтобы дать блокировке возможность сняться, а затем снова вызвать sqlite_step. Это можно повторять сколько угодно раз.

Когда становится доступна следующая строка результата, sqlite_step возвращает SQLITE_ROW. Данные строки хранятся в массиве указателей на строки, и 2-й параметр начинает указывать на этот массив.

После завершения всей обработки sqlite_step возвращает SQLITE_DONE или SQLITE_ERROR. SQLITE_DONE означает, что инструкция выполнена успешно, а SQLITE_ERROR — что произошла ошибка во время выполнения. (Подробности ошибки можно получить с помощью sqlite_finalize.) Попытка вызвать sqlite_step ещё раз после возврата SQLITE_DONE или SQLITE_ERROR является неправильным использованием библиотеки.

Когда sqlite_step возвращает SQLITE_DONE или SQLITE_ERROR, значения *pN и *pazColName устанавливаются в количество столбцов результирующего набора и имена столбцов — так же, как и при возврате SQLITE_ROW. Благодаря этому вызывающий код может узнать количество столбцов результата, а также их имена и типы данных, даже если результирующий набор пуст. Параметр *pazValue всегда устанавливается в NULL, если код возврата — SQLITE_DONE или SQLITE_ERROR. Если выполняемая инструкция SQL не возвращает результат (например, INSERT или UPDATE), то *pN устанавливается в ноль, а *pazColName — в NULL.

При неправильном использовании библиотеки, например при некорректном вызове sqlite_step, она попытается вернуть SQLITE_MISUSE. Это может произойти, если вызвать sqlite_step() для одной и той же виртуальной машины одновременно из двух или более потоков, повторно вызвать sqlite_step() после того, как она вернула SQLITE_DONE или SQLITE_ERROR, либо передать sqlite_step() недопустимый указатель на виртуальную машину. Не следует полагаться на код возврата SQLITE_MISUSE как на средство обнаружения ошибок. Неправильное использование интерфейса может остаться незамеченным и привести к аварийному завершению программы. SQLITE_MISUSE предназначен только как средство отладки — чтобы помочь обнаружить некорректное использование до возникновения проблем. Гарантируется, что логика обнаружения неправильного использования сработает не во всех случаях.

2.3 Удаление виртуальной машины

Каждую виртуальную машину, созданную с помощью sqlite_compile, в конечном итоге следует передать функции sqlite_finalize. Процедура sqlite_finalize() освобождает память и другие ресурсы, используемые виртуальной машиной. Если не вызвать sqlite_finalize(), в программе произойдёт утечка ресурсов.

Процедура sqlite_finalize также возвращает код результата, указывающий на успех или неудачу SQL-операции, выполненной виртуальной машиной. Значение, возвращённое sqlite_finalize(), будет таким же, как если бы тот же SQL-код выполнялся с помощью sqlite_exec. Сообщение об ошибке также будет таким же.

Допускается вызывать sqlite_finalize для виртуальной машины до того, как sqlite_step вернула SQLITE_DONE. Это прерывает выполняющуюся операцию. Частично выполненные изменения откатываются, а база данных возвращается в исходное состояние (если только с помощью предложения ON CONFLICT в выполняемом SQL-коде не выбран альтернативный алгоритм восстановления). Результат такой же, как если бы функция обратного вызова sqlite_exec вернула ненулевое значение.

Допускается также вызывать sqlite_finalize для виртуальной машины, которая ни разу не передавалась функции sqlite_step.

3.0 Расширенный API

Для использования SQLite необходимы только три основные процедуры, описанные в разделе 1.0. Однако существует множество других функций, предоставляющих полезные интерфейсы. К ним относятся:

int sqlite_last_insert_rowid(sqlite*);

int sqlite_changes(sqlite*);

int sqlite_get_table(
  sqlite*,
  char *sql,
  char ***result,
  int *nrow,
  int *ncolumn,
  char **errmsg
);

void sqlite_free_table(char**);

void sqlite_interrupt(sqlite*);

int sqlite_complete(const char *sql);

void sqlite_busy_handler(sqlite*, int (*)(void*,const char*,int), void*);

void sqlite_busy_timeout(sqlite*, int ms);

const char sqlite_version[];

const char sqlite_encoding[];

int sqlite_exec_printf(
  sqlite*,
  char *sql,
  int (*)(void*,int,char**,char**),
  void*,
  char **errmsg,
  ...
);

int sqlite_exec_vprintf(
  sqlite*,
  char *sql,
  int (*)(void*,int,char**,char**),
  void*,
  char **errmsg,
  va_list
);

int sqlite_get_table_printf(
  sqlite*,
  char *sql,
  char ***result,
  int *nrow,
  int *ncolumn,
  char **errmsg,
  ...
);

int sqlite_get_table_vprintf(
  sqlite*,
  char *sql,
  char ***result,
  int *nrow,
  int *ncolumn,
  char **errmsg,
  va_list
);

char *sqlite_mprintf(const char *zFormat, ...);

char *sqlite_vmprintf(const char *zFormat, va_list);

void sqlite_freemem(char*);

void sqlite_progress_handler(sqlite*, int, int (*)(void*), void*);

Все приведённые выше определения включены в заголовочный файл "sqlite.h", который входит в дерево исходного кода.

3.1 ROWID последней вставленной записи

Каждая строка таблицы SQLite имеет уникальный целочисленный ключ. Если в таблице есть столбец с именем INTEGER PRIMARY KEY, этот столбец служит ключом. Если столбца INTEGER PRIMARY KEY нет, ключом является уникальное целое число. К ключу строки можно обратиться в инструкции SELECT или использовать его в предложении WHERE либо ORDER BY, указав любое из имён "ROWID", "OID" или "_ROWID_".

При вставке записи в таблицу без столбца INTEGER PRIMARY KEY или если такой столбец есть, но его значение не указано в предложении VALUES инструкции INSERT, ключ генерируется автоматически. Значение ключа последней инструкции INSERT можно получить с помощью API-функции sqlite_last_insert_rowid.

3.2 Количество изменённых строк

API-функция sqlite_changes возвращает количество строк, вставленных, удалённых или изменённых с момента последнего перехода базы данных в состояние покоя. База данных считается «находящейся в состоянии покоя», если нет выполняющихся вызовов sqlite_exec и нет виртуальных машин, созданных с помощью sqlite_compile и ещё не уничтоженных функцией sqlite_finalize. В обычных случаях sqlite_changes возвращает количество строк, вставленных, удалённых или изменённых последним вызовом sqlite_exec либо с момента последнего вызова sqlite_compile. Однако если вызовы sqlite_exec вложены друг в друга (то есть если процедура обратного вызова одного вызова sqlite_exec вызывает другой sqlite_exec) или если вы вызываете sqlite_compile для создания новой виртуальной машины, пока существует другая виртуальная машина, смысл возвращаемого функцией sqlite_changes числа становится сложнее. Возвращаемое число включает любые изменения, которые впоследствии были отменены с помощью ROLLBACK или ABORT. Однако строки, удалённые в результате DROP TABLE, не учитываются.

SQLite выполняет команду "DELETE FROM table" (без предложения WHERE), удаляя таблицу, а затем создавая её заново. Это намного быстрее, чем удалять элементы таблицы по одному. Однако это также означает, что функция sqlite_changes вернёт ноль независимо от того, сколько элементов изначально было в таблице. Если необходимо получить точное количество удалённых элементов, используйте вместо этого "DELETE FROM table WHERE 1".

3.3 Выполнение запроса в память, полученную с помощью malloc()

Функция sqlite_get_table служит обёрткой над sqlite_exec: она собирает всю информацию из последовательных вызовов обратного вызова и записывает её в память, полученную с помощью malloc(). Эта удобная функция позволяет приложению получить полный результат запроса к базе данных за один вызов.

Основной результат работы sqlite_get_table — массив указателей на строки. В этом массиве есть один элемент для каждого столбца каждой строки результата. Результаты NULL представлены указателями NULL. Помимо обычных данных, в начале массива добавляется строка, содержащая имя каждого столбца результата.

Рассмотрим, например, следующий запрос:

SELECT employee_name, login, host FROM users WHERE login LIKE 'd%';

Этот запрос вернёт имя, логин и имя компьютера для каждого сотрудника, логин которого начинается с буквы "d". Если передать этот запрос функции sqlite_get_table, результат может выглядеть так:

nrow = 2
ncolumn = 3
result[0] = "employee_name"
result[1] = "login"
result[2] = "host"
result[3] = "dummy"
result[4] = "No such user"
result[5] = 0
result[6] = "D. Richard Hipp"
result[7] = "drh"
result[8] = "zadok"

Обратите внимание: значение "host" для записи "dummy" равно NULL, поэтому в этом элементе массива result[] находится указатель NULL.

Если результирующий набор запроса пуст, по умолчанию sqlite_get_table установит nrow в 0, а параметр result останется равным NULL. Однако если для прагмы EMPTY_RESULT_CALLBACKS задано значение ON, параметр result инициализируется только именами столбцов. Например, рассмотрим следующий запрос с пустым результирующим набором:

SELECT employee_name, login, host FROM users WHERE employee_name IS NULL;

По умолчанию результат будет таким:

nrow = 0
ncolumn = 0
result = 0

Но если для прагмы EMPTY_RESULT_CALLBACKS задано значение ON, результат будет следующим:

nrow = 0
ncolumn = 3
result[0] = "employee_name"
result[1] = "login"
result[2] = "host"

Память для хранения информации, возвращаемой функцией sqlite_get_table, выделяется с помощью malloc(). Однако вызывающая функция не должна пытаться освободить эту память напрямую. Вместо этого передайте всю таблицу функции sqlite_free_table, когда она больше не нужна. Функцию sqlite_free_table безопасно вызывать с указателем NULL, например, если результирующий набор пуст.

Процедура sqlite_get_table возвращает тот же целочисленный код результата, что и sqlite_exec.

3.4 Прерывание операции SQLite

Функцию sqlite_interrupt можно вызвать из другого потока или обработчика сигнала, чтобы прервать текущую операцию с базой данных при первой возможности. В этом случае процедура sqlite_exec (или её эквивалент), запустившая операцию с базой данных, вернёт SQLITE_INTERRUPT.

3.5 Проверка полноты инструкции SQL

Следующая функция интерфейса SQLite — это вспомогательная функция для проверки того, является ли строка полной инструкцией SQL. Если функция sqlite_complete возвращает true для переданной ей строки, значит, аргумент представляет собой полную инструкцию SQL. Это не гарантирует правильность синтаксиса инструкции, но по крайней мере позволяет знать, что она завершена. Если sqlite_complete возвращает false, для завершения инструкции SQL требуется дополнительный текст.

Для функции sqlite_complete инструкция SQL считается полной, если она заканчивается точкой с запятой.

Утилита командной строки sqlite использует функцию sqlite_complete, чтобы определить, когда нужно вызвать sqlite_exec. После получения каждой строки ввода sqlite вызывает sqlite_complete для всех данных во входном буфере. Если sqlite_complete возвращает true, вызывается sqlite_exec, а входной буфер очищается. Если sqlite_complete возвращает false, приглашение меняется на приглашение для продолжения ввода, после чего считывается ещё одна строка текста и добавляется во входной буфер.

3.6 Строка версии библиотеки

Библиотека SQLite экспортирует строковую константу с именем sqlite_version, содержащую номер версии библиотеки. Заголовочный файл содержит макрос SQLITE_VERSION с той же информацией. При необходимости программа может сравнить макрос SQLITE_VERSION со строковой константой sqlite_version, чтобы проверить, совпадают ли номера версий заголовочного файла и библиотеки.

3.7 Кодировка символов библиотеки

По умолчанию SQLite предполагает, что все данные используют символы фиксированного размера в 8 бит (iso8859). Однако если передать параметр --enable-utf8 скрипту configure, библиотека будет использовать символы переменной длины в кодировке UTF-8. Это влияет на операторы LIKE и GLOB, а также на функции LENGTH() и SUBSTR(). Статическая строка sqlite_encoding будет иметь значение "UTF-8" или "iso8859", указывая, с какими параметрами была скомпилирована библиотека. Кроме того, в заголовочном файле sqlite.h будет определён один из макросов SQLITE_UTF8 или SQLITE_ISO8859, в зависимости от выбранных параметров.

Обратите внимание: механизм кодировки символов, используемый SQLite, нельзя изменить во время выполнения. Это только параметр компиляции. Строка символов sqlite_encoding лишь сообщает, с какими параметрами была скомпилирована библиотека.

3.8 Изменение поведения библиотеки при блокировке файлов

Процедуру sqlite_busy_handler можно использовать для регистрации функции обратного вызова занятости в открытой базе данных SQLite. Эта функция будет вызываться каждый раз, когда SQLite попытается обратиться к заблокированной базе данных. Обычно функция обратного вызова выполняет какую-либо полезную работу или приостанавливается, чтобы дать блокировке возможность сняться. Если функция обратного вызова возвращает ненулевое значение, SQLite повторяет попытку доступа к базе данных, и цикл повторяется. Если функция обратного вызова возвращает ноль, SQLite прерывает текущую операцию и возвращает SQLITE_BUSY.

Аргументы функции sqlite_busy_handler — это непрозрачная структура, возвращённая функцией sqlite_open, указатель на функцию обратного вызова занятости и универсальный указатель, который будет передан в качестве первого аргумента этой функции обратного вызова. При вызове функции обратного вызова занятости SQLite передаёт ей три аргумента: универсальный указатель, переданный третьим аргументом функции sqlite_busy_handler, имя таблицы или индекса базы данных, к которым пытается обратиться библиотека, и количество попыток доступа библиотеки к таблице или индексу базы данных.

Для распространённого случая, когда требуется, чтобы функция обратного вызова занятости приостанавливала выполнение, библиотека SQLite предоставляет вспомогательную процедуру sqlite_busy_timeout. Первый аргумент функции sqlite_busy_timeout — указатель на открытую базу данных SQLite, а второй — количество миллисекунд. После вызова sqlite_busy_timeout библиотека SQLite будет ждать снятия блокировки не менее указанного количества миллисекунд, прежде чем вернуть SQLITE_BUSY. Если указать тайм-аут, равный нулю миллисекунд, будет восстановлено поведение по умолчанию.

3.9 Функции-обёртки _printf()

Четыре вспомогательные функции

  • sqlite_exec_printf()
  • sqlite_exec_vprintf()
  • sqlite_get_table_printf()
  • sqlite_get_table_vprintf()

реализуют те же возможности выполнения запросов, что и sqlite_exec и sqlite_get_table. Однако вместо полной инструкции SQL в качестве второго аргумента эти четыре функции _printf принимают строку формата в стиле printf. Инструкция SQL для выполнения формируется из этой строки формата и дополнительных аргументов, передаваемых в конце вызова функции.

Использование функций printf из SQLite вместо sprintf имеет два преимущества. Во-первых, при использовании функций printf из SQLite нет опасности переполнения статического буфера, которая существует при использовании sprintf. Функции printf из SQLite автоматически выделяют (а затем освобождают) столько памяти, сколько необходимо для хранения сформированных инструкций SQL.

Второе преимущество функций printf из SQLite перед sprintf — наличие двух новых спецификаторов формата, специально предназначенных для поддержки строковых литералов в SQL. В строке формата спецификатор %q работает почти так же, как %s: он считывает из списка аргументов строку, завершающуюся нулевым символом, и вставляет её в результат. Однако %q преобразует вставляемую строку, удваивая каждый символ одинарной кавычки (') в подставляемой строке. Это позволяет экранировать одинарную кавычку, иначе обозначающую конец строкового литерала. Спецификатор формата %Q работает аналогично: он преобразует одинарные кавычки, как %q, и дополнительно заключает полученную строку в одинарные кавычки. Если аргумент для спецификатора формата %Q — указатель NULL, результатом будет NULL без одинарных кавычек.

Рассмотрим пример. Допустим, вы пытаетесь вставить строковое значение в таблицу базы данных, причём это значение получено от пользователя. Предположим, вставляемая строка хранится в переменной с именем zString. Код для вставки может выглядеть так:

sqlite_exec_printf(db,
  "INSERT INTO table1 VALUES('%s')",
  0, 0, 0, zString);

Если переменная zString содержит текст "Hello", эта инструкция будет работать без проблем. Но предположим, что пользователь ввёл строку "Hi y'all!". Сформированная инструкция SQL будет выглядеть так:

INSERT INTO table1 VALUES('Hi y'all')

Это недопустимая инструкция SQL из-за апострофа в слове "y'all". Однако если вместо %s использовать спецификатор формата %q, как показано ниже:

sqlite_exec_printf(db,
  "INSERT INTO table1 VALUES('%q')",
  0, 0, 0, zString);

Тогда сформированная инструкция SQL будет выглядеть так:

INSERT INTO table1 VALUES('Hi y''all')

Здесь апостроф экранирован, и инструкция SQL имеет корректный формат. При динамическом формировании SQL-кода из данных, которые могут содержать символ одинарной кавычки ('), всегда рекомендуется использовать функции printf из SQLite и спецификатор формата %q вместо sprintf.

Если вместо %q использовать спецификатор формата %Q, как показано ниже:

sqlite_exec_printf(db,
  "INSERT INTO table1 VALUES(%Q)",
  0, 0, 0, zString);

Тогда сформированная инструкция SQL будет выглядеть так:

INSERT INTO table1 VALUES('Hi y''all')

Если значение переменной zString равно NULL, сформированная инструкция SQL будет выглядеть так:

INSERT INTO table1 VALUES(NULL)

Все приведённые выше функции _printf() построены на основе следующих двух функций:

char *sqlite_mprintf(const char *zFormat, ...);
char *sqlite_vmprintf(const char *zFormat, va_list);

Процедура sqlite_mprintf() работает как стандартная библиотечная функция sprintf(), но записывает результат в память, полученную с помощью malloc(), и возвращает указатель на выделенный буфер. Функция sqlite_mprintf() также поддерживает описанные выше расширения %q и %Q. Функция sqlite_vmprintf() — версия той же процедуры, принимающая переменное число аргументов. Строку, на которую указывают возвращаемые этими функциями указатели, следует освободить, передав её функции sqlite_freemem().

3.10 Выполнение фоновых задач во время обработки больших запросов

Процедуру sqlite_progress_handler() можно использовать для регистрации в базе данных SQLite функции обратного вызова, которая будет периодически вызываться во время длительных вызовов sqlite_exec(), sqlite_step() и различных функций-обёрток.

Функция обратного вызова вызывается через каждые N операций виртуальной машины, где N задаётся вторым аргументом sqlite_progress_handler(). Третий и четвёртый аргументы sqlite_progress_handler() — это указатель на вызываемую процедуру и указатель void, который будет передан ей в качестве первого аргумента.

Время выполнения каждой операции виртуальной машины может зависеть от множества факторов. Для ПК с частотой 1 ГГц типичное значение составляет от полумиллиона до трёх миллионов операций в секунду, но оно может быть значительно выше или ниже в зависимости от запроса. Поэтому планировать фоновые операции на основе количества операций виртуальной машины сложно. Вместо этого рекомендуется вызывать функцию обратного вызова достаточно часто (например, через каждые 1000 инструкций), а для определения необходимости запуска фоновых задач использовать внешние таймеры.

4.0 Добавление новых функций SQL

Начиная с версии 2.4.0, SQLite позволяет расширять язык SQL новыми функциями, реализованными на C. Для этого используется следующий интерфейс:

typedef struct sqlite_func sqlite_func;

int sqlite_create_function(
  sqlite *db,
  const char *zName,
  int nArg,
  void (*xFunc)(sqlite_func*,int,const char**),
  void *pUserData
);
int sqlite_create_aggregate(
  sqlite *db,
  const char *zName,
  int nArg,
  void (*xStep)(sqlite_func*,int,const char**),
  void (*xFinalize)(sqlite_func*),
  void *pUserData
);

char *sqlite_set_result_string(sqlite_func*,const char*,int);
void sqlite_set_result_int(sqlite_func*,int);
void sqlite_set_result_double(sqlite_func*,double);
void sqlite_set_result_error(sqlite_func*,const char*,int);

void *sqlite_user_data(sqlite_func*);
void *sqlite_aggregate_context(sqlite_func*, int nBytes);
int sqlite_aggregate_count(sqlite_func*);

Интерфейс sqlite_create_function() используется для создания обычных функций, а sqlite_create_aggregate() — для создания новых агрегатных функций. В обоих случаях параметр db — это открытая база данных SQLite, в которой следует зарегистрировать функции, zName — имя новой функции, nArg — количество аргументов, а pUserData — указатель, который без изменений передаётся реализации функции на C. Обе процедуры возвращают 0 в случае успеха и ненулевое значение при возникновении ошибки.

Длина имени функции не может превышать 255 символов. Любая попытка создать функцию с именем длиннее 255 символов приведёт к ошибке.

Для обычных функций обратный вызов xFunc вызывается при каждом вызове функции. Реализация xFunc должна вызвать один из интерфейсов sqlite_set_result_..., чтобы вернуть результат. Процедуру sqlite_user_data() можно использовать для получения указателя pUserData, переданного при регистрации функции.

Для агрегатных функций обратный вызов xStep вызывается для каждой строки результата, а в конце вызывается xFinalize для вычисления окончательного результата. Процедура xStep может использовать интерфейс sqlite_aggregate_context() для выделения памяти, уникальной для данного экземпляра функции SQL. Эта память автоматически освобождается после вызова xFinalize. Процедуру sqlite_aggregate_count() можно использовать, чтобы узнать, сколько строк данных было передано агрегатной функции. Обратный вызов xFinalize должен вызвать один из интерфейсов sqlite_set_result_..., чтобы задать окончательный результат агрегатной функции.

Теперь SQLite реализует все встроенные функции с помощью этого интерфейса. Дополнительные сведения и примеры создания новых функций SQL см. в исходном коде SQLite, в файле func.c.

5.0 Многопоточность и SQLite

Если SQLite скомпилирована с макросом препроцессора THREADSAFE, установленным в 1, её можно безопасно использовать одновременно из двух или более потоков одного процесса. Однако у каждого потока должен быть собственный указатель sqlite*, возвращённый функцией sqlite_open. Одновременный доступ двух или более потоков к одному и тому же указателю sqlite* небезопасен.

В предварительно скомпилированных библиотеках SQLite, доступных на веб-сайте, версии для Unix скомпилированы с выключенным THREADSAFE, а версии для Windows — с включённым THREADSAFE. Если вам нужна другая конфигурация, библиотеку необходимо пересобрать.

В Unix указатель sqlite* нельзя переносить через системный вызов fork() в дочерний процесс. После вызова fork() дочерний процесс должен открыть собственный экземпляр базы данных.

6.0 Примеры использования

sqlite в файле src/shell.c дерева исходного кода. Дополнительная информация о sqlite доступна на странице cli.html. См. также исходный код интерфейса SQLite для Tcl в файле src/tclsqlite.c.

Эта страница последний раз обновлялась 2025-07-12 15:11:36Z

SQLite is in the Public Domain.
https://sqlite.org/c_interface.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API