orefkov / v8sqlite

Внешняя компонента 1С 8 для работы с базами sqlite

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

V8Sqlite

Нативная внешняя компонента для 1С 8 для работы с базами данных sqlite. Позволяет выполнять запросы к базам данных sqlite и получать их результаты в виде ТаблицыЗначений или массива массивов.

Поддерживает работу в:

  • Windows x86
  • Windows x64
  • Linux x64

Сама библиотека sqlite подключена статически, то есть внедрена в ВК. Используется версия 3.44.0. Версию sqlite можно узнать запросом

    select sqlite_version()

Кодировка текста

Базы данных sqlite хранят текст в одной кодировке, выбираемой при создании базы данных - UTF-8 либо UTF-16. Несмотря на то, что работать возможно с базами с любой кодировкой, стоит учитывать, что внутри 1С для данных типа "Строка" используется кодировка UTF-16, поэтому при чтении текста из баз с этой кодировкой движку sqlite не нужно выполнять каждый раз перекодировку текста из UTF-8 в UTF-16 и наоборот. Поэтому из соображений производительности, если вы планируете пользоваться базой данных в-основном в 1С, создавайте её в кодировке UTF-16. Для этого после первого открытия базы данных выполните pragma encoding:

    // Создать пустую базу в файле
    ИмяФайла = ПолучитьИмяВременногоФайла("db");
    база.ОткрытьБазуДанных(ИмяФайла);
    база.Выполнить("pragma encoding='UTF-16'");

Поддержка Unicode

В компоненте к движку sqlite добавлена минимальная поддержка регистронезависимости Unicode-символов, для работы функций upper, lower, fold, title, unaccent, like и collate nocase. Правильно обрабатываются символы только из первой плоскости Unicode (до 0xFFFF). Кроме того, преобразование регистра выполняется только "один символ - в один символ", т.е. некоторые случаи, при которых один символ может в другом регистре стать двумя символами и наоборот - не учитываются. Для регистронезависимого сравнения используется fold.

Сборка

Собирается как cmake проект в Visual Studio Community Edition 2022. Под windows проверял в MSVC и Clang. Под linux собирается подключением к удалённой машине с установленным Clang, собирал на clang-16. В бинарной сборке:

  • win x86 собрана MSVC
  • win x64 - clang-cl 16
  • Linux x64 - clang-16, в двух версиях, под Ubuntu 18.04 с GLIBC 2.25, под Ubuntu 22 - с GLIBC 2.34

Использование

Подключается как обычная нативная ВК, например так

    Функция ПодключитьВК()

        ПутьКВК = КаталогПрограммы();

        СистемнаяИнформация = Новый СистемнаяИнформация;

        Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 или СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
            ПутьКВК = ПутьКВК + "v8sqlite.dll";
        ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
            ПутьКВК = ПутьКВК + "libv8sqlite.so";
        КонецЕсли;

        Если не ПодключитьВнешнююКомпоненту(ПутьКВК, "v8sqlite", ТипВнешнейКомпоненты.Native) Тогда
            Предупреждение("Не удалось подключить внешнюю компоненту " + ПутьКВК);
            Возврат Ложь;
        КонецЕсли;
        Возврат Истина;

    КонецФункции // ПодключитьВК()

После подключения доступен к созданию объект внешней компоненты, через который и можно будет работать с базой даных sqlite.

    база = Новый("AddIn.v8sqlite.v8sqlite");

Свойства объекта

Версия / Version

Строка, только чтение. Версия компоненты.


БросатьОписаниеОшибки / ThrowErrorDescription

Булево, чтение/запись. По умолчанию Ложь.

Флаг, нужно ли при возникновении исключения добавлять текстовое описание ошибки штатным для ВК методом AddError. Дело в том, что вывод такого сообщения в окно сообщений невозможно подавить. Даже если вы отловили исключение с помощью Попытка Исключение и программа продолжает работу - в окно сообщений всё-равно выдаст текст ошибки. Если значение свойства Ложь, то текст ошибки не будет выдавать в исключении (будет просто штатное "Ошибка при вызове метода объекта"), которое не выдает сообщение в случае отлова попыткой. Описание ошибки в этом случае можно прочитать в свойстве ОписаниеОшибки.


ОписаниеОшибки / ErrorDescription

Строка. Только чтение.
Содержит текстовое описание последней ошибки. Ошибка может быть как возвращенная sqlite базой, так и самой компоненты.

    Попытка
        база.Выполнить("create table test(a,b,c");
    Исключение
        Сообщить(база.ОписаниеОшибки);
    КонецПопытки;


БазаДанныхОткрыта / isDataBaseOpen

Булево. Только чтение.
Показывает, открыта ли в данный момент база данных.


ПоследнийИд / LastId

Число. Только чтение.
После выполнения операций вставки выдает ID последней вставленной строки.


СтрокИзменено / Changes

Число. Только чтение.
Показывает, сколько строк было вставлено/изменено во время выполнения последнего запроса.


Методы объекта

ОткрытьБазуДанных(ИмяФайла) / OpenDataBase(FileName)

Открывает базу данных. Если была открыта база данных, она закрывается. Если файла с заданным именем не существует, будет создана новая пустая база данных.

Параметры:

  • ИмяФайла: Строка, обязательный. Имя открываемого файла. Специальное имя ":memory:" открывает базу данных в памяти. Поддерживается имена в URI формате, позволяющие задавать дополнительные параметры отрытия файла.

Возвращаемое значение - нет. При ошибке выбрасывает исключение.

Пример:

    база = Новый("AddIn.v8sqlite.v8sqlite");
    // Открыть базу в памяти
    база.ОткрытьБазуДанных(":memory:");
    ...
    // Создать пустую базу в файле
    ИмяФайла = ПолучитьИмяВременногоФайла("db");
    база.ОткрытьБазуДанных(ИмяФайла);


ЗакрытьБазуДанных() / CloseDataBase()

Закрывает открытую базу данных, если она была ранее открыта. Параметров нет. Возвращаемого значения нет.


Выполнить(ТекстЗапроса) / Exec(QueryText)

Выполняет переданный текст запроса с помощью sqlite3_exec. Служит в основном для выполнения запросов insert/update/delete, то есть не возвращающих результата. Можно указывать текст нескольких запросов, разделяя их ;.

Пример:

    база = Новый("AddIn.v8sqlite.v8sqlite");
    база.ОткрытьБазуДанных(":memory:");
    база.Выполнить("
    |create table test(a,b,c);
    |insert into test values
    |(1, 2.3, null),
    |('text', x'414243', datetime('now'))
    |");

Возвращаемого значения нет.


ПодготовитьЗапрос(ИмяЗапроса, ТекстЗапроса) / PrepareQuery(QueryName, QueryText)

Подготавливает запрос для дальнейшего неоднократного выполнения.

Параметры:

  • ИмяЗапроса - Строка, обязательный. Любое уникальное в пределах этой базы имя для дальнейшего обращения к запросу. Если запрос с таким именем уже был подготовлен ранее, он будет заменён.
  • Текст запроса - Строка, обязательный. Текст sql-запроса.

Возвращаемого значения нет. При ошибке в тексте запроса - выкинет исключение.

Пример:

    база = Новый("AddIn.v8sqlite.v8sqlite");
    база.ОткрытьБазуДанных(":memory:");
    база.ПодготовитьЗапрос("Запрос1", "
    |select * from test where a = @p1
    |");

УстановитьПараметр(ИмяЗапроса, ИмяПараметра, ЗначениеПараметра) / BindParam(QueryName, ParamName, ParamValue)

Устанавливает значение sql-параметра для ранее подготовленного запроса.

Параметры:

  • ИмяЗапроса - Строка, обязательный. Имя, которое использовалоь в методе ПодготовитьЗапрос. Задаёт, для какого запроса устанавливается параметр.
  • ИмяПараметра - Строка или Число. Задает, какой параметр устанавливается. Передаётся либо имя параметра, либо его номер. Нумерация параметров с 1.
  • ЗначениеПараметра - Число, Строка, ДвоичныеДанные, Дата, Неопределено, Null, Булево. Необязательный. При отсутствии, Неопределено или Null - устанавливает null. Дата конвертируется в формат YYYY-MM-DD HH:MM:SS - так, как возвращает функция sqlite datetime. Булево преобразуется в 0 или 1.

Возвращаемого значения нет.

Пример:

    база = Новый("AddIn.v8sqlite.v8sqlite");
    база.ОткрытьБазуДанных(":memory:");
    база.ПодготовитьЗапрос("Запрос1", "
    |select * from test where a = @p1
    |");

    ...

    база.УстановитьПараметр("Запрос1", "@p1", 1);

ВыполнитьЗапрос(Запрос, ФорматОтвета, [КолонкиСДатой]) / ExecQuery(Query, AnswerFormat, [DateColumns])

Выполняет запрос с выдачей результата.

Параметры:

  • Запрос - Строка, обязательный. Здесь можно либо указать имя ранее подготовленного запроса, либо просто текст запроса. В этом случае запрос подготавливается, выполняется и закрывается. В случае подготовленного запроса он выполняется с учётом установленных параметров, после все установленные параметры сбрасываются.
  • ФорматОтвета - Строка, обязательный. Задаёт, в каком формате будет выдаваться результат выполнения запроса. Может принимать значения "JSON" или "ТаблицаЗначений" / "ValueTable". Регистронезависимый.
  • КолонкиСДатой - Строка, необязательный. Перечисленные через запятую названия или номера колонок, значения в которых нужно преобразовать в Дату. Нумерация колонок с нуля. Чтобы преобразование сработало, реальное значение должно быть строкой длиной 19 символов, т.е. датой в формате "YYYY-MM-DD HH:MM:SS", так, как выдаёт функция sqlite datetime. Компонента не парсит дату, а просто берёт куски из этой строки и расставляет в нужном 1С формате.

Возвращаемое значение: строка, если выполняется запрос select. Для остальных видов запросов - пустое значение. При возникновении sql-ошибки - выкидывает исключение.

Возвращаемая строка зависит от указанного при вызове метода формате. Для формата "ТаблицаЗначений" - выдаётся строка, которая методом ЗначениеИзСтрокиВнутр преобразуется в Таблицу значений. Названия колонок запроса становятся именем и заголовком колонок таблицы значений.

Для формата "JSON" возвращается строка, которая через XDTO преобразуется в массив. Элементы массива - тоже массивы, строки результата запроса. Самой первой строкой идёт массив с названиями колонок.

Преобразование типов sqlite:

  • integer, real - преобразуются в тип 1С Число.
  • text - в тип Строка.
  • null - в Null.
  • blob - в ДвоичныеДанные.

Если для колонки задано преобразование в Дату, компонента попытается это сделать, см. описание параметра КолонкиСДатой.

Пример:

    // Получение как ТЗ
    тз = ЗначениеИзСтрокиВнутр(база.ВыполнитьЗапрос("
        |select a, b, c as dt
        |from test where a = 100
        |", "ТаблицаЗначений", "dt"));

    // Получение как массива массивов
    Функция JSONВМассив(текст)
        ч = Новый ЧтениеJSON;
        ч.УстановитьСтроку(текст);
        Возврат СериализаторXDTO.ПрочитатьJSON(ч);
    КонецФункции

    ...

    результат = JSONВМассив(база.ВыполнитьЗапрос("
    |select a [col a], b, c as dt
    |from test
    |", "json", "dt"));


УдалитьЗапрос(ИмяЗапроса) / RemoveQuery(QueryName)

Закрывает ранее подготовленный запрос и удаляет его из списка запросов. При закрытии базы все подготовленные запросы удаляются автоматически.

Параметры:

  • ИмяЗапроса - строка, обязательный. Имя запроса, использованное ранее в методе ПодготовитьЗапрос.

Возвращаемого значения нет.

Пример:

    база.УдалитьЗапрос("Запрос1");

About

Внешняя компонента 1С 8 для работы с базами sqlite

License:MIT License


Languages

Language:C 93.1%Language:C++ 6.8%Language:CMake 0.1%