<?php // Полная загрузка сервисных книжек, создан 2025-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='\
неэстетично…
имхается проще и красивше рекурсивную процедуру заюзать…
Как-то уж очень мудрено…
Самый простой способ избавиться от дублей — использовать процедуры. Ведь они именно для этого придуманы?
Если есть желание сэкономить число сравнений, почему бы не построить индекс? Например так:
Показать полностью
всяко пошустрее будет
А не проще написать так:
Показать полностью
При этом никакого дублирования кода нет,
и удобочитаемость остается.
И почему нельзя редактировать комментарии?
Я имел ввиду такой код:
Если (ТЗ.НомерСтроки = 1) ИЛИ
(ТЗ.Ключ_1<>ПредЗначение_Ключ_1) ИЛИ
(ТЗ.Ключ_2<>ПредЗначение_Ключ_2) ИЛИ
…
(ТЗ.Ключ_N<>ПредЗначение_Ключ_N) Тогда
// БЛОК 1 Создать новый документ
// БЛОК 2 Заполнить заголовок документа
Если (ТЗ.НомерСтроки > 1) Тогда
// сменились ключи
// БЛОК 3 Заполнить подвал документа
// БЛОК 4 Записать / вывести документ
КонецЕсли;
КонецЕсли;
* и предварительного просмотра нет — тоже плохо 🙁
Итак.
Показать полностью
Дублирование записи документа/вывода печатной формы после цикла не так страшно.
Хотя тоже можно избежать добавив в таблицу фиктивную последнюю строку.
Как оригинальный вариант решения имеет право на существование…
(1) (2) Рекурсивная, скорее всего, на сравнение и заполнение строк ТЧ. Иногда может получиться громоздко, т.к. нужно хранить / передавать в процедуру(ы) ключи и все, что там необходимо будет сделать. Я попытался реализовать одной вспомогательной универсальной процедурой с четко определенными параметрами.
(3) +1 хороший индекс! Единственное, добавил бы после свертки ТЗИндекс
Показать полностью
(4) (5) (6) от объединения условий отказался, — можно запутаться в условиях. Блоки 3 и 4 всегда должны идти после блока 5 (для текущего документа), их дублирования условиями не избежать. Если добавлять фиктивную строку, — необходимо проверить/задать уникальные ключи для нее.
Я бы это сделал так:
Показать полностью
(10) а если ТЗ.ПолучитьЗначение(1,»Ключ_1″) = ПолучитьПустоеЗначение() ?
Замерил время выполнения, 10т записей
традиционный, (6) (10) 100%
3 ключа, значения от 1 до 100:
(3) от +40% до +50%
мой: от +250 до +300%
3 ключа, значения от 1 до 10:
(3) +400%
мой: +180%
1 ключ, значения от 1 до 10, от 1 до 100
(3) от + 20% до +40%
мой: +130%
Ст’оит ли красота времени?
Хотя мож и стоит. Сравнивается с голым циклом с парой-тройкой условий и присваиваний.
(8) Согласен, никто не гарантирует порядка после свертки, правда ни разу не сталкивался с такой ситуацией :-/ (Хотя в реальных алгоритмах дополнительную сортировку включаю в код — надежность дороже 😉 )
(12) такой индекс даст прирост производительности на больших объемах данных, т.е. когда сложность условия в цикле превысит накладные расходы на индексирование, т.е. к примеру при десятке ключей на сотне тысяч записей
ну или иначе — при варировании ключевых условий, тут уже выйдет на первое место гибкость :-/
> 3 ключа, значения от 1 до 10:
> (3) +400%
> мой: +180%
Кстати, очень интересный результат. На что ушло время?
(15) Замерял не в отладчике, а с пом. _GetPerformanceCounter() . Отладчик показывает +100% Максимум времени ушло на Свернуть()
(14) при десятке ключей на сотне т: минус 40%
(16) хм… Такая картина — несовпадение результатов разных методов замера наверное объясняется «особенностями» работы платформы, в частности уборщика мусора.
(17) т.е. сфера применения у него найдется, и не только в плане «красивости» кода? буду рад, если пригодится 🙂
когда-то на проклабе обнаружил конкурс на самый быстрый метод удаления строк из ТЗ (правда он к тому времени уже закончился), заинтересовался и написал свой вариант с использованием такого индексирования — занятный вариант получился, но не без «особенностей» 🙂
(11)
Ну, сделай
ключ1 = «bcad7cf3-2fd3-4286-a654-139b37840a79»
(18) да, полезный конкурс, столько особенностей при оптимизации обнаружилось, вплоть до наличия запятой в НоваяКолонка() 🙂
(19) )))) Ну тогда какое-нить другое красивое слово.
(18) если не против, добавлю в статью с ссылкой.
(21) Добро
Внесу свои пять копеек в решение задачи "Простой метод исключения дублирования кода в одном из часто используемых алгоритмов."
Показать полностью
Очевидно, что представленный код работает медленнее, чем при индексировании. Но ведь речь идет о простоте и понятности алгоритма и кода? Не так ли?
Так. Включаем в статью?
(24)
Я не против.
Можно еще описать решение (6). Считаю, что оно вполне справляется с поставленной в статье задаче.
Остальные решения стоит позиционировать не только как избавление от дублей, но как универсальные решения, которые не зависят от списка ключевых полей.
З.Ы. Попробуй длинный комментарий к процедуре ИзмененияКлючейТЗ() сделать в несколько строк, а то он у меня на экран не помещается — неудобно читать статью. 🙁
(25) насчет (6) ( и (10) ) да, подсознательно фильтровал универсальные, но для полной картины включу. Можно, в принципе и его сделать универсальным, вынеся операции сравнения и присваивания в функции.
По комментарию — разве он у тебя не переносится на след. строки? Хотя, при копировании в конфигуратор лучше, чтобы строки были короткие.
(26)
> По комментарию — разве он у тебя не переносится на след. строки?
Есть ощущение, что строки внутри конструкции ( code ) ( /code) не переносятся… 🙁 В IE7
Но это претензия скорее к саппорту, чем к тебе. Сделай опиcание ИмяКолонкиНач и ИмяКолонкиКон в несколько строк, возможно, будет лучше…
З.Ы.
Решение описанное в (10) не стоит внимания, потому-что неправильное.
(27) Чем оно неправильное? Решения (6) и (10) — одно и тоже, просто (10) дописано до конца, а в (6) код + идея.
(28)
Да, действительно, решение (10) правильное. Я невнимательно его прочтала. Приношу извинения перед автором за напрасный поклеп. 😉
(23)
Внесу свою копейку.
В Функции ПроверитьСтрокуТаблицы(ТЗ, СписокКлючей)
надо добавить объявление локальных переменных НомСтр и М1.
Перем НомСтр и М1;
Иначе может поменять глобальные переменные с такими именами.
(30) Правильное замечание.
В (23) вкралась ошибка. В условиях вместо НомСтр должно быть написано НомерСтроки.
Получается, что локальными переменными нужно объявлять: Перем ии, Колонка.
(30) нашел, таки, но про колонку забыл. 😉
Правило про переменные, — это классика. Стараюсь его выполнять. Ну, вряд ли кто-то додумается сделать глобальные переменные с такими короткими и простыми именами, но вероятность есть. Обычно добавляется префикс «гл».
(31) (23) в статье скорректировано, ошибка с НомСтр изначально была устранена. Кстати, зачем передавался НомерСтроки ?
(32)
> Кстати, зачем передавался НомерСтроки ?
Наверно, для бОльшей универсальности. Ведь можно написать и так:
Показать полностью
(33) Да, действительно.
еще метод