Spec-Zone.ru › SQLite

Примечание редактора: Данный документ описывает SQLite версии 2, которая была устаревшей и заменена SQLite3 в 2004 году. Этот документ сохранен в качестве части исторического архива 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 или создания новой базы данных SQLite используйте функцию sqlite_open. Первый аргумент — имя базы данных. Второй аргумент предназначен для указания, будет ли база данных использоваться для чтения и записи или только для чтения. Однако в текущей реализации второй аргумент функции 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) и четвертый параметр (имена столбцов) остаются действительными и могут использоваться для определения количества и имен столбцов результата, если результат был. По умолчанию обратный вызов не вызывается, если результат пуст.

Функция обратного вызова обычно должна возвращать 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 of 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 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 attempts to create or access a file database file that is larger that 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, по одному для каждой строки вывода, и, наконец, вызове sqlite_finalize для очистки после завершения выполнения SQL.

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-й, 3-й и 4-й параметры функции sqlite_step передают ту же информацию, что и 2-й, 3-й и 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, или если таблица имеет столбец 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 может быть использована для регистрации обратного вызова busy с открытой базой данных SQLite. Обратный вызов busy будет вызван всякий раз, когда SQLite пытается получить доступ к базе данных, которая заблокирована. Обратный вызов, как правило, выполняет некоторую полезную работу или, возможно, переходит в режим ожидания, чтобы дать возможность снять блокировку. Если обратный вызов возвращает ненулевое значение, то SQLite пытается снова получить доступ к базе данных, и цикл повторяется. Если обратный вызов возвращает ноль, то SQLite прерывает текущую операцию и возвращает SQLITE_BUSY.

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

В общем случае, когда требуется, чтобы обратный вызов при занятости библиотеки SQLite приостановился, библиотека 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-запрос для выполнения генерируется из этой строки формата и любых дополнительных аргументов, присоединённых к концу вызова функции.

Использование функций SQLite printf вместо 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(), и возвращает указатель на буфер, выделенный с помощью malloc(). sqlite_mprintf() также понимает расширения %q и %Q, описанные выше. sqlite_vmprintf() — это версия функции varargs той же функции. Указатель на строку, возвращаемый этими функциями, должен быть освобождён путём передачи его в sqlite_freemem().

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

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

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

Время выполнения каждой виртуальной машинной операции может варьироваться в зависимости от многих факторов. Типичное значение для ПК с частотой 1 ГГц составляет от 0,5 до 3 миллионов операций в секунду, но может быть значительно выше или ниже в зависимости от запроса. Поэтому трудно запланировать фоновые операции на основе виртуальных машинных операций. Вместо этого рекомендуется планировать обратные вызовы относительно часто (например, каждые 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*, возвращённый функцией sqlite_open. Никогда не безопасно для двух или более потоков обращаться к одному и тому же указателю sqlite* одновременно.

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

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

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

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

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

Spec-Zone.ru

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