Показано с 1 по 6 из 6

Тема: CmpSysExec.SysExecute4 и команда более 255 символов

  1. #1

    Question CmpSysExec.SysExecute4 и команда более 255 символов

    Добрый день
    Вопрос в заголовке. Как быть?
    Я отправляю SQL-запрос. И ограничение в 255 символов - это, объективно, мало
    Даже небольшой запрос на запись трёх параметров уже вместе с управляющими символами ~240 символов (с учётом предварительного перевода в UTF8)

    Код:
    //Шлём SQL-запрос
    fbSe4
    (
    	xExecute   := fbRiseEdge.Q,
    	sCommand   := sCommand_Real,
    	xDone      => xDone,
    	xBusy      => xBusy,
    	xError     => xError
    );
    Спасибо

    P.S.
    Ну, разве что, придётся делать это несколькими запросами. Сначала INSERT, затем несколько UPDATE-ов. Разве что, как то так
    Ну а SELECT придётся делать исключительно через SELECT * и фильтровать уже дальше лишнее через код
    Последний раз редактировалось aaaSashaMGGU; 10.06.2024 в 14:04.

  2. #2

  3. #3

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Спасибо!
    Спасибо!
    Спасибо!

  4. #4

    По умолчанию

    Всё заработало
    Может, кому пригодится:

    Объявления:
    Код:
    (*-------------------------------------------------------------------------------------------------------------------
    Перед использованием нужно добавить в файл /etc/freetds.conf секции:
    //(в рамках примера в сервере collation = Cyrillic_General_CI_AS)
    //
    //[read]
    //	host = <IP-адрес сервера> (например, host = 10.2.7.70)
    //	port = 1433
    //	tds version = 7.3
    //   client charset = WINDOWS-1251 (кодировка выбирается в зависимости от конкретной задачи)
    //
    //[write]
    //	host = <IP-адрес сервера> 
    //	port = 1433
    //	tds version = 7.3
    //   client charset = UTF-8
    //
    //где:
    //host - IP-адрес сервера БД (например, host = 10.2.7.70)
    //client charset - используемая кодировка (выбирается в зависимости от настроек и содержимого БД)
    -------------------------------------------------------------------------------------------------------------------*)
    FUNCTION_BLOCK My_MsSQL_CLIENT_Write (*ФБ для использования MsSQL-клиента. Запись*)
    
    //Входы-Выходы
    VAR_IN_OUT
    	xExecute: BOOL; //Запуск	
    END_VAR
    
    //Входы
    VAR_INPUT
    	sSqlStatement : WSTRING(2047); //Текст SQL-запроса
    	sBD_Name      : WSTRING(255);	 //Имя БД
    END_VAR
    
    //Выходы
    VAR_OUTPUT
    	//Стандартные выходы
    	xDone  : BOOL; //Признак конца работы
    	xBusy  : BOOL; //Признак занятости
    	xError : BOOL; //Признак ошибки
    END_VAR
    
    //Внутренние параметры
    VAR
    	//R-триггер для фиксации запуска работы ФБ 
    	fbRiseEdge: R_TRIG;
    	
    	//Команда отправки на контроллерную консоль
    	sCommand_Real: STRING(2047);
    	
    	//Текст SQL-запроса в UTF8
    	sSqlStatement_UTF8: STRING(2047);
    	
    	//Имя БД в UTF8
    	sBD_Name_UTF8: STRING(255);
    	
    	//Результат. Он здесь не нужен, но инструкция на блок говорит, что надо его всё равно использовать
    	Result: STRING(255);
    		
    	//ФБ для отправки команд на контроллерную консоль
    	fbSe5: CmpSysExec.SysExecute5;
    END_VAR
    
    //Константы
    VAR CONSTANT
    	//Команда отправки на контроллерную консоль
    	sCommand: STRING(2047) := 'echo "#SQL#" | bsqldb -S write -U sa -P password -D #BD_NAME#';
    END_VAR
    Код:
    Код:
    //Проверяем признак запуска
    fbRiseEdge(CLK := xExecute);
    xExecute := FALSE;
    
    //Если появился признак запуска...
    IF fbRiseEdge.Q THEN
    	
    	//Текст SQL-запроса в правильной кодировке UTF8
    	STU.ConvertUTF16toUTF8(ADR(sSqlStatement), ADR(sSqlStatement_UTF8), SIZEOF(sSqlStatement_UTF8), FALSE);
    	sCommand_Real := OSU.ReplaceSubstring(sCommand, '#SQL#', sSqlStatement_UTF8);
    	
    	//Имя БД в правильной кодировке UTF8
    	STU.ConvertUTF16toUTF8(ADR(sBD_Name), ADR(sBD_Name_UTF8), SIZEOF(sBD_Name_UTF8), FALSE);
    	sCommand_Real := OSU.ReplaceSubstring(sCommand_Real, '#BD_NAME#', sBD_Name_UTF8);
    END_IF
    
    //Блок отправки команды через контроллерную консоль
    fbSe5
    (
    	xExecute        := fbRiseEdge.Q,                              //По переднему фронту происходит отправка команды
    	//xAbort        := qqq1,                                      //По переднему фронту происходит прерывание работы блока
    	pCommand        := ADR(sCommand_Real),                        //Указатель на строку команды (не более 2047 символов)
    	szCommand       := TO_DWORD(STU.StrLenA(ADR(sCommand_Real))), //Длина строки команды
    	pOutput         := ADR(Result),                               //Указатель на текущую строку ответа
    	szOutput        := SIZEOF(Result),                            //Размер буфера текущей строки ответа в байтах
    	xDone           => xDone,                                     //Флаг завершения работы блока
    	//xAborted      => qqq2,                                      //Флаг прерывания работы блока
    	xError          => xError,                                    //Флаг ошибки
    	xBusy           => xBusy                                      //Флаг «ФБ в процессе работы»
    	//eError        => qqq3,                                      //Код ошибки
    	//uiOutputSize  => qqq4,                                      //Длина текущей строки ответа
    );

  5. #5

    По умолчанию

    Немного подумав над всей этой ситуацией, кажется, нашёл решение поинтереснее...
    Ведь моя задача отправлять SQL-запросы. И (ну вот он такой уж я, мне стыдно) 2047 символов мне тоже не хватает...
    В инструкции на bsqldb нашёл параметр [-i input_file] с описанием Name of script file, containing SQL.
    Я же правильно понимаю, что строку
    Код:
    sCommand: STRING(2047) := 'echo "#SQL#" | bsqldb -S write -U sa -P password -D #BD_NAME#';
    можно вполне записать как
    Код:
    sCommand: STRING(255) := 'bsqldb -S write -U sa -P password -D #BD_NAME#' -i SQL.txt;
    В SQL.txt заранее подсунуть мой ~60кб SQL-запрос - и всё должно отработать как надо
    И все эти выкрутасы со сверхдлинными строками вообще не понадобятся. Ну, разве что, при формировании самого файла, но там всё должно быть просто

    Так будет работать? А то пока что проверить негде и не на чем
    Спасибо

  6. #6

    По умолчанию

    Всё получилось, всё работает с запросами любой длины
    Объявления
    Код:
    (*-------------------------------------------------------------------------------------------------------------------
    Перед использованием нужно добавить в файл /etc/freetds.conf секции:
    //(в рамках примера в сервере collation = Cyrillic_General_CI_AS)
    //
    //[read]
    //	host = <IP-адрес сервера> (например, host = 10.2.7.70)
    //	port = 1433
    //	tds version = 7.3
    //   client charset = WINDOWS-1251 (кодировка выбирается в зависимости от конкретной задачи)
    //
    //[write]
    //	host = <IP-адрес сервера> 
    //	port = 1433
    //	tds version = 7.3
    //   client charset = UTF-8
    //
    //где:
    //host - IP-адрес сервера БД (например, host = 10.2.7.70)
    //client charset - используемая кодировка (выбирается в зависимости от настроек и содержимого БД)
    -------------------------------------------------------------------------------------------------------------------*)
    FUNCTION_BLOCK My_MsSQL_CLIENT_Write (*ФБ для использования MsSQL-клиента. Запись*)
    
    //Входы-Выходы
    VAR_IN_OUT
    	xExecute: BOOL; //Запуск	
    END_VAR
    
    //Входы
    VAR_INPUT
    	sSqlStatement : WSTRING(65535); //Текст SQL-запроса
    	sBD_Name      : WSTRING(255);	  //Имя БД
    END_VAR
    
    //Выходы
    VAR_OUTPUT
    	//Стандартные выходы
    	xDone  : BOOL; //Признак конца работы
    	xBusy  : BOOL; //Признак занятости
    	xError : BOOL; //Признак ошибки
    END_VAR
    
    //Внутренние параметры
    VAR
    	//R-триггер для фиксации запуска работы ФБ 
    	fbRiseEdge: R_TRIG;
    	
    	//Команда отправки на контроллерную консоль
    	sCommand_Real: STRING(255);
    	
    	//Текст SQL-запроса в UTF8
    	sSqlStatement_UTF8: STRING(65535);
    	
    	//Имя БД в UTF8
    	sBD_Name_UTF8: STRING(255);
    	
    	//ФБ для отправки команд на контроллерную консоль
    	fbSe4: CmpSysExec.SysExecute4;
    	
    	//Немножко магии для работы с файлом
    	pResult : POINTER TO SysFile.SysTypes.RTS_IEC_RESULT;
    	hFile   : POINTER TO SysFile.SysTypes.RTS_IEC_HANDLE;
    END_VAR
    
    //Константы
    VAR CONSTANT
    	//Команда отправки на контроллерную консоль
    	sCommand: STRING(255) := 'bsqldb -S write -U sa -P Password -D #BD_NAME# -i /home/SQL.txt';
    END_VAR
    Код
    Код:
    //Проверяем признак запуска
    fbRiseEdge(CLK := xExecute);
    xExecute := FALSE;
    
    //Если появился признак запуска...
    IF fbRiseEdge.Q THEN
    	
    	//Имя БД в правильной кодировке UTF8
    	STU.ConvertUTF16toUTF8(ADR(sBD_Name), ADR(sBD_Name_UTF8), SIZEOF(sBD_Name_UTF8), FALSE);
    	sCommand_Real := OSU.ReplaceSubstring(sCommand, '#BD_NAME#', sBD_Name_UTF8);
    	
    	//Текст SQL-запроса в правильной кодировке UTF8
    	STU.ConvertUTF16toUTF8(ADR(sSqlStatement), ADR(sSqlStatement_UTF8), SIZEOF(sSqlStatement_UTF8), FALSE);
    	
    	//Пишем файл перед отправкой самого SQL-запроса
    	hFile := SysFile.SysFileOpen('/home/SQL.txt', SysFile.ACCESS_MODE.AM_WRITE, pResult);
    	SysFile.SysFileWrite(hFile, ADR(sSqlStatement_UTF8), TO_UDINT(StrLenA(ADR(sSqlStatement_UTF8))), pResult); //Пишем
    	SysFile.SysFileClose(hFile);
    END_IF
    
    //Блок отправки команды через контроллерную консоль
    fbSe4
    (
    	xExecute   := fbRiseEdge.Q,  //Запуск на исполнение по переднему фронту  
    	sCommand   := sCommand_Real, //Команда Linux - например 'ls /'
    	xAbort     := FALSE,         //Аварийный останов процесса
    	sOutput    => ,              //Массив строк для сохранения вывода процесса
    	cntReadStr => ,              //Количество считанных строк вывода процесса
    	xOverFlow  => ,              //Признак переполнения массива sOutput
    	xDone      => xDone,         //Признак завершённости процесса и/или того, что в данный момент не выполняется процесс Linux
    	xAborted   => ,              //Признак прерывания по пользовательской команде
    	xError     => xError,        //Признак невозможности запуска из-за возникновекния ошибки
    	xBusy      => xBusy,         //Процесс выполняется
    	eErrorCode =>                //Код ошибки
    );

Похожие темы

  1. Ответов: 4
    Последнее сообщение: 12.03.2025, 14:57
  2. CmpSysExec
    от 6385428 в разделе ПЛК2хх
    Ответов: 19
    Последнее сообщение: 10.07.2023, 10:30
  3. Ответов: 3
    Последнее сообщение: 14.06.2023, 08:14
  4. Ответов: 3
    Последнее сообщение: 26.03.2019, 12:31
  5. Вывод символов в ПР200
    от KIPDIM в разделе Программируемые реле
    Ответов: 2
    Последнее сообщение: 26.12.2016, 03:42

Метки этой темы

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •