PDA

Просмотр полной версии : ПЛК200. Работа с SQLite. SysExecute4 и SysExecute5. Не могу выполнить длинную команду



PaPoV
29.07.2023, 19:34
Всем здоровья!

Работаю с БД SQLite. Пока отправлял короткие запросы, то CmpSysExec.SysExecute4 для этого подходит хорошо. Но запрос с условиями и объединением таблиц получается больше чем 255 символов и на вход CmpSysExec.SysExecute4 такую команду я уже не могу подать.

Попробовал использовать CmpSysExec.SysExecute5. ФБ завершает свое выполнение без ошибок, но в ответе всегда пустая строка. Даже на короткий запрос.

Попробовал использовать CmpSysExec.SysExecute4 разбивая команду на 2 строки. После первой строки в ответе пустая строка. Я так понял, что приглашение ввода ">" я не могу увидеть через CmpSysExec.SysExecute4, потому что это приглашение ввода от sqlite3 а не от linux. Но ладно, я знаю, что отправил не всю команду, в ответ ничего не получил - значит ошибки нет. Тогда отправляю вторую часть команды, а в ответе все равно пусто.

Может быть есть у кого пример работы с SQL через CmpSysExec.SysExecute5?

Код который дает пустые строки не могу выложить :( я его со злости удалил. Остался только рабочий код с короткими запросами через CmpSysExec.SysExecute4.

PaPoV
29.07.2023, 20:24
Я знаю. Команда рабочая. Я брал короткую команду, которая выполнялась с SysExecute4, и передавал указатель на нее в SysExecute5. Формирование самой команды не менял.

А когда разбивал на две строки, то да, стоило бы проверить, но забыл о таком способе.

PaPoV
29.07.2023, 23:04
В общем, добрался до документации (https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_CmpSysExec_v3.0.pdf) на сайте ОВЕН. Оказывается SysExecute5 каждую новую строку из терминала пишет по заново по переданному ей указателю, перетирая предыдущие строки и последняя строка обязательно пустая. То есть необходимо вручную во время выполнения ФБ подкидывать ему новый указатель.

Вот такой код у меня заработал


FUNCTION_BLOCK SQLQuery IMPLEMENTS itfSQLQuery
VAR_INPUT
xExecute: BOOL;
END_VAR
VAR_OUTPUT
xDone: BOOL;
xBusy: BOOL;
xError: BOOL;
usiCurQuery : USINT := 0; //текущий запрос 0 - запрос обработан; 1 - количество строк; 2- данные
END_VAR
VAR
sPathToDb: STRING := '/home/ftp/kormplus_plc.db'; //путь к базе данных
sCommand: STRING(2047); //переменная для целой команды
sSQLQuery: STRING(2000); //переменная для запроса
sTable : STRING; //Имя таблицы
sColumn : STRING; //Имя столбца
sWhereStatement : STRING(2000); //условия запроса
iItemsCount : INT; //количество доступных строк в таблице
fbSe5 : CmpSysExec.SysExecute5;
fbRiseEdge : R_TRIG;
// Результат выполнения запроса
asResult : ARRAY[1..255] OF STRING(255);

x : UINT;
i : USINT := 0;
// количество строк в ответе
usiCountOfStrings: USINT;
// TRUE - при выдаче ответа произошло переполнение массива, часть информации потеряна
xOverFlow: BOOL;
END_VAR
VAR CONSTANT
// шаблон запроса, можно отредактировать под себя
// см. https://linux.die.net/man/1/sqlite3
c_sCommand: STRING(255) := 'sqlite3 #PATH_TO_FILE# "#SQL#"';
c_sCountSelect : STRING(255) := 'SELECT COUNT(#COLUMN#) FROM #TABLE# #WHERE#;';
c_sSelect : STRING(255) := 'SELECT #COLUMN# FROM #TABLE# #WHERE#;';
END_VAR

fbRiseEdge(CLK := xExecute);

IF fbRiseEdge.Q THEN
i := 1;
xOverFlow := FALSE;
usiCountOfStrings := 0;
END_IF

fbSe5
(
xExecute := xExecute,
pCommand := ADR(sCommand),
szCommand := TO_DWORD(STU.StrLenA(ADR(sCommand))),
pOutput := ADR(asResult[i]),
szOutput := SIZEOF(asResult[i]),
uiOutputSize => x,
xDone => xDone,
xBusy => xBusy,
xError => xError
);

IF fbSe5.xBusy AND asResult[i] <> '' AND i < 255 THEN
i := i + 1;
IF i = 255 OR x > 255 THEN
xOverFlow := TRUE;
END_IF
END_IF

IF fbSe5.xDone THEN
usiCountOfStrings := i -1;
END_IF

lazy
12.03.2025, 14:47
Добрый день!

Планируется ли, что бы при работе с SQL ф.блоки SysExecute4 и SysExecute5 возвращали бы в xError и eError что то кроме FALSE и 0?

Евгений Кислов
12.03.2025, 14:57
Добрый день!

Планируется ли, что бы при работе с SQL ф.блоки SysExecute4 и SysExecute5 возвращали бы в xError и eError что то кроме FALSE и 0?

Добрый день.
Не планируется.
SysExecute - это способ вызова утилит ОС. Он ничего не знает про назначение этих утилит и выполняет исключительно функции прослойки.