DBEng32 (7.0.0.3, SEQ) – исправление ошибки “CodeBase –56” при использовании 1SQLite для 1С:Предприятие 7.7




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

26 Comments

  1. CheBurator

    ..блин.. истина где-то рядом…

    Reply
  2. hogik

    (1)(Сhe Burashka)

    🙂 Истина тут: http://infostart.ru/blogs/482/

    Reply
  3. JohnyDeath

    Ну хорошо, что нашлось решение, а то негоже такому красивому проекту загнутся из-за этой проблемы.

    Конечно, лечше чтоб эти правки были сделаны в 1sqlite, а то получается, что вы хотите улучшить 7-ку, а выходит что вы нарушили авторские права, подправив движок 1с

    Reply
  4. hogik

    (3)(JohnyDeath)

    “нарушили авторские права, подправив движок 1с”

    У меня вопрос не по теме. Под какую формулировку в законе об авторских правах попадают разработки такого рода?

    P.S. А ошибка ““CodeBase –56” есть и без использования 1SQLite. Только вероятность её появления очень мала.

    Reply
  5. JohnyDeath

    (4) Ну, на сколько я помню, нельзя каким-либо образом патчить/исправлять файлы программы. Если я не прав — поправьте меня.

    Reply
  6. Abadonna

    (5) Мне почему-то кажется, что если я честно купил программу, то лично для себя могу делать с ней, что хочу: хоть запатчить, хоть испортить 😉

    Reply
  7. JohnyDeath

    (6) мне тоже так хочется думать, но, по-моему, законодателям так не кажется.

    Reply
  8. hogik

    (5)(JohnyDeath)

    “Если я не прав — поправьте меня”

    Не знаю. Я давно хочу это выяснить.

    Вот это уже отменили?

    Лицо, правомерно владеющее экземпляром программы для ЭВМ, вправе без согласия правообладателя и без выплаты дополнительного вознаграждения декомпилировать или поручать декомпилирование программы для ЭВМ с тем, чтобы изучать кодирование и структуру этой программы при следующих условиях:

    информация, необходимая для взаимодействия независимо разработанной данным лицом программы для ЭВМ с другими программами, недоступна из других источников;

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

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

    http://www.fips.ru/avp/law/3523-1S.HTM

    Reply
  9. kolodina

    думаю, если некто купил программу — то может делать с ней все что хочет… авторские права тут не нарушаются… авторские права нарушаются, если вы купили программу — и выдаете ее за свою…

    пропатченный движок я установила на двух станциях — у меня выхода нету… целая подсистема написана с использованием 1sqlite… если его оттуда убрать — тормоза будут несказанные…

    Reply
  10. kolodina

    а вот вопрос — я поставила пропатченный движок на двух станциях — а остальные пока не трогала… могут быть проблемы? спасибо.

    Reply
  11. hogik

    (10)

    Да.

    Reply
  12. JohnyDeath

    Hogik, я вот фразу одну недопонял:

    "В остальных случаях пользователь может управлять режимом выполнения запроса с помощью функций Начать/Зафиксировать/ОтменитьТранзакцию()."

    надо ли это понимать так:

    Если я выполняю запрос вне модуля проведения (например в отчете), то мне необходимо писАть:

    Код
    НачатьТранзакцию();
    Запрос.ВыполнитьЗапрос(ТекстЗапроса);
    ЗафиксироватьТранзакцию();

    Показать полностью

    ?

    Reply
  13. hogik

    (12)(JohnyDeath)

    “то мне необходимо писАть”

    Необходимо, перед тем как “писАть”, принять решение, что важней в конкретном алгоритме – скорость выполнения запроса или ожидание освобождения заблокированной таблицы в других сессиях. Т.е. если запрос выполнять вне транзакции, то он будет выполняться медленно, но в других сессиях не будет возникать ожидания освобождения блокировки таблицы. Если запрос выполнять внутри транзакции, то он будет выполняться быстро, но в других сессиях будет возникать ожидание освобождения таблицы.

    Reply
  14. JohnyDeath

    (13) т.е. я тебя понял правильно и пример для внешнего отчета написал правильно?

    и рекомендации сделать в 1sqlite Begin/EndReadSequence() опциональным здесь как раз-таки будет очень кстати?

    Reply
  15. hogik

    (14)(JohnyDeath)

    “для внешнего отчета написал правильно?”

    На этот вопрос нет однозначного ответа. Правильно будет и то, что Вы написали. И без запуска транзакции тоже будет правильно. Всё зависит от поставленных Вами задач в алгоритме. Или Ваш вопрос ко мне в чем-то другом?

    “сделать в 1sqlite Begin/EndReadSequence() опциональным ”

    Да. Но, думаю, имеет смысл иметь не два режима – “включено/выключено”, а ещё и, типа, — “авто”. Т.е. внутри транзакции эти методы вместе с блокировкой таблицы имеет смысл выполнять в 99% случаев, т.к. блокировка существует и по другим причинам. И если транзакция уже активизирована по другим причинам, то уж и заодно имеет смысл активизировать Begin/EndReadSequence().

    Reply
  16. JohnyDeath

    (15)Или Ваш вопрос ко мне в чем-то другом?

    Я вот что имел ввиду: как бы ты поступил, если бы знал, что этот запрос во внешнем отчете выполняется продолжительное время

    Reply
  17. hogik

    (15)(JohnyDeath)

    “как бы ты поступил”

    Применительно к 1SQLite я б выяснил:

    1) Что означает “продолжительное время”.

    2) Используются ли таблицы запроса в других, параллельно выполняющихся, задачах.

    3) Сколько времени выполняется данная выборка штатными средствами 1Са.

    И т.д. Т.е. опять однозначного ответа не может быть.

    А если говорить вообще, то я б постарался построить систему так, чтобы таких вопросов (проблем) не возникало.

    P.S. Посмотрите, пожалуйста, сообщения (20), пункт #3 в http://infostart.ru/profile/2905/blogs/482/ Мне очень интересно Ваше мнение по поводу данного “явления”.

    Reply
  18. hogik

    +(17)

    Я ошибся. Не пункт #3, а пункт #2.

    Reply
  19. JohnyDeath

    (17) всё-таки, наверное, мы не поняли друг друга (= я плохо изъяснился)

    Спрошу по-другому: "Не решает ли этот патч движка проблему автоматически? Т.е. я, как программист 1С, просто напишу

    Код
    Запрос.Выполнить(ТекстЗапроса)

    Показать полностью

    а пропатченный движок сам всё разрулит:

    1) если он выполняется внутри транзакции (например, в модуле проведения), то он выбирает "быстрый способ"

    2) если вне транзакции, то "медленный" (с отключенным ReadSequence)

    ?

    Reply
  20. JohnyDeath

    (18) Ответил в той теме.

    Reply
  21. hogik

    (19)(JohnyDeath)

    “проблему автоматически?”

    Он это и делает.

    Reply
  22. hogik

    (20)(JohnyDeath)

    Прочел Ваш ответ. Суть происходящего мне ясна. Мой вопрос был в другом. Вам это “явление” ничего не напоминает? И как люди работают с этим при наличии такого “явления”?

    Reply
  23. JohnyDeath

    (22) » И как люди работают с этим при наличии такого “явления”?»

    Наверное так: пользователей натаскивают на то, что если они видят эту ошибку, ждут чуть-чуть и пробуют ещё 😉 ( а вообще лучше у kiruh-и спросить, он Фокс использует очень широко)

    (21) “проблему автоматически?”

    Он это и делает.


    Меня просто смутила фраза из описания: В остальных случаях пользователь может управлять режимом выполнения запроса с помощью функций Начать/Зафиксировать/ОтменитьТранзакцию().

    Т.е. я могу «смело» ставить пропатченный движок и не переписывать те места, где я использую 1sqlite?

    Reply
  24. hogik

    (23)(JohnyDeath)

    “я могу «смело» ставить пропатченный движок и не переписывать те места, где я использую”

    Да. Но учитывать фразу “только для тестирования”… ;-)))

    А что касается моего вопроса про “явление”, то, похоже, мне опять не удалось сформулировать вопрос. Но отложим это. Сейчас, думаю, важней разобраться с 1SQLite.

    Reply
  25. JohnyDeath

    (24) Да. Но учитывать фразу “только для тестирования”… ;-)))

    именно поэтому я и поставил слово СМЕЛО в кавычки. 😉

    Reply
  26. CheBurator

    прям как разведчики…

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *