Переключение на Главную Страницу Страницы: [1] 2 3 ... 16 ОтправитьПечать
Очень популярная тема (более 25 ответов) Провайдер OLE DB для ТП (число прочтений - 69399 )
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Провайдер OLE DB для ТП
23. Сентября 2007 :: 04:59
Печать  
Продолжение темы: http://www.1cpp.ru/forum/YaBB.pl?num=1178779637/0

Итак, изначально для реализации предлагалась следующая структура провайдера:
Цитата:
Во-первых, OLE DB не умеет эффективно делать частичные выборки (SELECT TOP) - есть здесь ветка, где мы со spock'ом пинали OLE DB по этому поводу. Поэтому поставщик должен использовать методы XBase по работе с таблицами: USE, GO, SEEK.

Отсюда вытекает следующая организация провайдера:
- Сначала провайдеру устанавливается некоторая ОПОРНАЯ ТАБЛИЦА, для таблицы устанавливается индекс и/или фильтр. Далее навигация по таблице происходит методами XBase. Основное предназначение опорной таблицы: выдача ИДшников видимых на данный момент записей. Идентификатор поля с ИДшниками, таким образом, также должен указываться при инициализации провайдера.

- Далее. Провайдер XBase-методами собирает ИДшники и использует их для выполнения прямого запроса типа SELECT ... FROM Таблица WHERE Таблица.ID IN (СписокИДшников). Результат этого запроса скармливается табличному полю как основной набор данных. Таким образом, при инициализации провайдеру необходимо передать еще и текст этого запроса.

- Быстрый поиск реализуется командой SEEK - что быстро, т.к. использует индексы.

Естественно, для указания имени опорной таблицы должно быть возможно использовать псевдонимы типа $Справочник.Номенклатура и т.п.


Далее от kiruh'и поступила следующая мысль:
Цитата:
И еще - непонятно - набор индексов в ДБФ крайне ограничен, а в табличном поле хочется иметь возможность произвольных сортировок. В FoxPro народ, в этих случаях, как я понял - создают индексированные представления.


Мне, в качестве, некоторого (не самого лучшего) заменителя видится, так сказать, фиксированный режим работы провайдера. Т.е. провайдер выполняет запрос, получает некий большой набор данных и постепенно его скармливает в ТП. Т.е., фактически, он работает как таблица значений. В целом, не самый удачный режим, но иногда может быть полезен. Возможно, он даже будет быстрее работать, чем с использованием промежуточной выгрузки в ТЗ.

В любом случае, такой режим сделать гораздо проще, чем динамический. Поэтому с него я и начал Подмигивание Если даже он не будет сильно полезным, то для обкатки по любому сойдет.

Альфа-версия провайдера находится здесь: http://uzhast.fatal.ru/vfp.oledb.provider/

Провайдер работает в фиксированном режиме, т.е. выполняет запрос и постепенно отдает данные в ТП по требованию. Методы, которые поддерживает провайдер можно посмотреть в тестовой обработке.

Изменения в 1С++:
- сильнее всего подверглась переделке система OleDb (ну вот, spock меня теперь точно убьет Печаль) - чтобы получить возможность повторного использования кода.

- был добавлен набор прокси-классов, обеспечивающих возможность модификации классов OleDb без необходимости перекомпиляции компоненты провайдера.

- небольшие изменения в функционале ТП - я использую свои контекст-классы, которые не кастятся к CDataProvider через dynamic_cast.

- в компоненту подключены boost'овские смартпойнтеры. Писать велосипедный shared_ptr мне что-то не захотелось. Если кому слишком сложно качать boost, могу выслать только заголовочные файлы (этого достаточно).

Для доработки я выбрал версию 2.5. Потому что, глянув на код в 2.0.3, решил, что это будет проще Подмигивание Хотя, в итоге, думаю перенести поддержку провайдера в 2.0.3. Ночные сборки меня по прежнему не вдохновляют. Особенно, в свете последних изменений, связанных с параметрами по умолчанию.

Компонента провайдера представляет собой солюшен для VS2005 с интегрированным IC. Также там используется boost и STLport.
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #1 - 23. Сентября 2007 :: 05:06
Печать  
Некоторый функционал 1С++ временно пострадал. В частности, временно отключен функционал для использования подготовленных запросов. Также изменен алгоритм выборки данных результата запроса OLE DB. Если раньше данные выбирались порциями по 50 строк, то сейчас по одной. Так что, возможно замедление выполнения обычных запросов через OLE DB.
  
Наверх
 
IP записан
 
artbear
1c++ developer
1c++ moderator
Отсутствует


Эх, дайте что-нибудь новенькое
да полезное потести

Сообщений: 6303
Местоположение: Москва
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #2 - 24. Сентября 2007 :: 05:48
Печать  
Uzhast писал(а) 23. Сентября 2007 :: 04:59:
- в компоненту подключены boost'овские смартпойнтеры. Писать велосипедный shared_ptr мне что-то не захотелось. Если кому слишком сложно качать boost, могу выслать только заголовочные файлы (этого достаточно).

Я использую замечательные смартпойнтеры - sh_ptr, sh_array. Написаны они не мной, но пока полностью меня устраивают.
По сравнению с бустовскими они сильно упрощены, но в принципе почти весь функционал соблюден.
Задачи по поддержанию времени жизни объектов и массивов они выполняют.
Находятся в 2.5, папка System

Но можешь выслать мне хедеры бустовских смартпойнтеров, вычленив их из буста?

Uzhast писал(а) 23. Сентября 2007 :: 04:59:
Для доработки я выбрал версию 2.5. Потому что, глянув на код в 2.0.3, решил, что это будет проще Подмигивание Хотя, в итоге, думаю перенести поддержку провайдера в 2.0.3. Ночные сборки меня по прежнему не вдохновляют. Особенно, в свете последних изменений, связанных с параметрами по умолчанию.

А чем тебе эти правки не нравятся?
  

OpenConf developer :: http://openconf.1cpp.ru&&FormEx developer :: http://formex.dorex.ru&&1C++ active developer && tester :: www.1cpp.ru
Наверх
GTalkSkype/VoIPICQ  
IP записан
 
sedmin
1c++ developer
Отсутствует


I Hate Fat YaBB 2!

Сообщений: 862
Зарегистрирован: 24. Мая 2006
Re: Провайдер OLE DB для ТП
Ответ #3 - 24. Сентября 2007 :: 06:07
Печать  
Uzhast писал(а) 23. Сентября 2007 :: 04:59:
Ночные сборки меня по прежнему не вдохновляют. Особенно, в свете последних изменений, связанных с параметрами по умолчанию.

А что с параметрами по умолчанию? Что-то критичное? Может быть, я что-то пропустил? Ужас

Если ты про то, что в 2.0.3 Артур это не залил, то тут я с тобой соглашусь.
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #4 - 24. Сентября 2007 :: 06:32
Печать  
artbear писал(а) 24. Сентября 2007 :: 05:48:
Я использую замечательные смартпойнтеры - sh_ptr, sh_array. Написаны они не мной, но пока полностью меня устраивают.

Это потому, что ты бустовских не видел.

artbear писал(а) 24. Сентября 2007 :: 05:48:
По сравнению с бустовскими они сильно упрощены, но в принципе почти весь функционал соблюден.

"Почти весь" - слишком сильно сказано. Более того, в указанных тобой классах нет минимально необходимого функционала. Например:
1) Нет корректного приведения к булевому типу (это не просто operator bool (), но даже его нет).
2) Нет аналогов static_cast, dynamic_cast и const_cast для смартпойнтера.
3) Нет оператора <, а значит нет возможности хранить указатели в std::map.
4) Самого по себе этого указателя не достаточно. Как минимум еще нужен аналог boost::scoped_ptr.

Ну, а вот что касается фичастости:
1) Возможность передать в смартпойнтер указатель на производный класс. При этом объект будет корректно удален даже в случае, когда у базового класса нет виртуального деструктора.
2) Возможность переопределить операцию удаления. Что позволяет использовать смартпойнтер для автоочистки ресурсов, не являющихся памятью. Вот пример отсюда
Код
Выбрать все
typedef shared_ptr<void> handle;

handle createProcess()
{
    shared_ptr<void> pv(CreateProcess(), CloseHandle);
    return pv;
}
 


При удалении последнего смартпойнтера будет автоматически вызван CloseHandle. Также можно просто заставить смартпойнтер выполнить некоторых завершающий код (без удерживания какого-либо указателя) - при выходе из блока.
3) shared_ptr удачно взаимодействует с weak_ptr, который содержит указатель на объект, но не препятствует его удалению. Когда будет удален последний shared_ptr, все weak_ptr инвалидируются.

Что же касается класса sh_array, то он вообще не имеет права на существование. В стандартной библиотеке есть просто замечательный класс std::vector, который по всем параметрам лучше обычных массивов в стиле C. Поэтому работать с массивами при помощи new CObject [N] - просто нет никакого смысла.

artbear писал(а) 24. Сентября 2007 :: 05:48:
Но можешь выслать мне хедеры бустовских смартпойнтеров, вычленив их из буста?

Чисто смартпойнтеры выдирать не так просто (есть вроде какой-то специальный утиль для этого...). Могу прислать всю директорию с заголовками (<2mb).

artbear писал(а) 24. Сентября 2007 :: 05:48:
Uzhast писал(а) 23. Сентября 2007 :: 04:59:
Для доработки я выбрал версию 2.5. Потому что, глянув на код в 2.0.3, решил, что это будет проще Подмигивание Хотя, в итоге, думаю перенести поддержку провайдера в 2.0.3. Ночные сборки меня по прежнему не вдохновляют. Особенно, в свете последних изменений, связанных с параметрами по умолчанию.

А чем тебе эти правки не нравятся?

Тем, что ломают работающий промышленный код Улыбка и приводят к тому, что функции 1С++ ведут себя не так, как принято в 1С повсеместно.

Во-первых. Например, раньше можно было писать ИндексированнаяТаблица.ВыбратьСтроку (). А теперь нельзя. Можно только, например, ИндексированнаяТаблица.ВыбратьСтроку (0). Так же видел, что кто-то еще жаловался на такое поведение с параметрами по умолчанию.

Во-вторых, подобное поведение не соответствует стандартному. Если я пишу
Код
Выбрать все
Процедура ХитроеСложение (А = 2, Б = 3) 


То я могу вызывать ее как ХитроеСложение (3). И мне не надо писать ХитроеСложение (3,). А в 1С++ надо  Улыбка
  
Наверх
 
IP записан
 
spock
1c++ developer
1c++ moderator
Отсутствует



Сообщений: 822
Местоположение: Новосибирск
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #5 - 24. Сентября 2007 :: 06:37
Печать  
Пока лениво лезть в код stl Нерешительный  , но расскажи вкратце преимущества std::vector
  
Наверх
ICQ  
IP записан
 
spock
1c++ developer
1c++ moderator
Отсутствует



Сообщений: 822
Местоположение: Новосибирск
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #6 - 24. Сентября 2007 :: 06:39
Печать  
Я за Boost (давно слежу за ее развитием), но тут надо всем договариваться...
  
Наверх
ICQ  
IP записан
 
JohnyDeath
1c++ power user
1c++ donor
Отсутствует



Сообщений: 3050
Местоположение: Волгоград
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #7 - 24. Сентября 2007 :: 06:45
Печать  
По сабжу:
1. А быстрый поиск есть? У меня чего-то не получилось его прикрутить.
2. При нажатии на клавишу "END" вываливается предупреждение "Невозможно получить следующую строку данных"
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #8 - 24. Сентября 2007 :: 06:51
Печать  
spock писал(а) 24. Сентября 2007 :: 06:37:
Пока лениво лезть в код stl Нерешительный  , но расскажи вкратце преимущества std::vector

Автоуправление памятью. Вектор сам выделяет память и освобождает в деструкторе и за
этим совсем не надо следить. По сути это практически scoped_ptr для простого сишного массива.

Возможность простого построения динамического, авторасширяющегося массива. Со стандартным массивом это сплошной гемор. Стандартом C++ гарантируется (ассимпотически) константное время добавления элементов в конец массива.

Удобная передача массива в функции. Мы передаем ссылку на массив в функцию и эта функция без труда может узнать размер массива через метод size.

Иногда возникает необходимость вернуть массив из функции. С вектором это проходит нормально.

Для передачи вектора в сишную функцию (которая хочет получить указатель на первый элемент и дальше с ним работать) можно использовать просто &vector [0].

STL-фенечки типа insert - мы говорим вектору, что хотим вставить куда-нибудь в середину массива набор элементов и вектор сам выделит память (если необходимо), сдвинет часть элементов в конец и скопирует требуемые.

Это пока то, что вспомнилось. Но вообще очень простой и удобный класс. Считается самым "ходовым".
  
Наверх
 
IP записан
 
JohnyDeath
1c++ power user
1c++ donor
Отсутствует



Сообщений: 3050
Местоположение: Волгоград
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #9 - 24. Сентября 2007 :: 06:52
Печать  
+ Ещё один крайне неприятный момент:
Как я понял, те данные по ключевому полю, которые в данный момент отображаются, открываются только в режиме просмотра  Печаль
т.е. если я написал запрос
Код
Выбрать все
Select Дог.iddoc as [Док $Документ.ДоговораОСАГО]
from $Документ.ДоговораОСАГО as Дог 


и сделал ключевое поле = "Док", то при двойном клике на любом документе в ТП он будет открываться в режиме просмотра. Тоже самое происходит при открытии этого дока в "родном" журнале.
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #10 - 24. Сентября 2007 :: 06:52
Печать  
JohnyDeath писал(а) 24. Сентября 2007 :: 06:45:
По сабжу:
1. А быстрый поиск есть? У меня чего-то не получилось его прикрутить.
2. При нажатии на клавишу "END" вываливается предупреждение "Невозможно получить следующую строку данных"

Спасибо Улыбка

1. Быстрый поиского нету пока. Для статического варианта провайдера поиск, похоже, будет не совсем быстрый - с полным перебором по колонке.

2. О! А "END" понажимать я и не пробовал! Щас попробуем...
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #11 - 24. Сентября 2007 :: 06:54
Печать  
JohnyDeath писал(а) 24. Сентября 2007 :: 06:52:
+ Ещё один крайне неприятный момент:
Как я понял, те данные по ключевому полю, которые в данный момент отображаются, открываются только в режиме просмотра  Печаль
т.е. если я написал запрос
Код
Выбрать все
Select Дог.iddoc as [Док $Документ.ДоговораОСАГО]
from $Документ.ДоговораОСАГО as Дог 


и сделал ключевое поле = "Док", то при двойном клике на любом документе в ТП он будет открываться в режиме просмотра. Тоже самое происходит при открытии этого дока в "родном" журнале.

Открытие объекта по двойному клику сделано в событии "ПолеВыбор" - оно от провайдера не зависит. Можешь в этом событии сделать все, что тебе надо Улыбка
  
Наверх
 
IP записан
 
spock
1c++ developer
1c++ moderator
Отсутствует



Сообщений: 822
Местоположение: Новосибирск
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #12 - 24. Сентября 2007 :: 06:54
Печать  
Меня интересует, прежде всего, как он выделяет память при resize'е
  
Наверх
ICQ  
IP записан
 
JohnyDeath
1c++ power user
1c++ donor
Отсутствует



Сообщений: 3050
Местоположение: Волгоград
Зарегистрирован: 19. Мая 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #13 - 24. Сентября 2007 :: 06:57
Печать  
Uzhast писал(а) 24. Сентября 2007 :: 06:54:
JohnyDeath писал(а) 24. Сентября 2007 :: 06:52:
+ Ещё один крайне неприятный момент:
Как я понял, те данные по ключевому полю, которые в данный момент отображаются, открываются только в режиме просмотра  Печаль
т.е. если я написал запрос
Код
Выбрать все
Select Дог.iddoc as [Док $Документ.ДоговораОСАГО]
from $Документ.ДоговораОСАГО as Дог 


и сделал ключевое поле = "Док", то при двойном клике на любом документе в ТП он будет открываться в режиме просмотра. Тоже самое происходит при открытии этого дока в "родном" журнале.

Открытие объекта по двойному клику сделано в событии "ПолеВыбор" - оно от провайдера не зависит. Можешь в этом событии сделать все, что тебе надо Улыбка

Я немного не про то. Похоже, что текущая выборка захватывает весь объект. Т.е. одинэсина думает, что его кто-то открыл в текущий момент.
  
Наверх
 
IP записан
 
Uzhast
1c++ power user
Отсутствует



Сообщений: 1341
Зарегистрирован: 30. Августа 2006
Пол: Мужской
Re: Провайдер OLE DB для ТП
Ответ #14 - 24. Сентября 2007 :: 07:00
Печать  
spock писал(а) 24. Сентября 2007 :: 06:54:
Меня интересует, прежде всего, как он выделяет память при resize'е

Это зависит от реализации STL. Стандарт устанавливает только набор классов для стандартной библиотеки и их открытый интерфейс. Но, скорее всего, ресайз происходит как выделение нового блока, копирование содержимого по новому адресу и прибивание старого блока.

Надо учитывать, что вектор обычно выделяет память несколько больше, чем реально требуется. Например, в STLport, если исчерпывается выделенный запас, то под новый блок выделяется в два раза больше памяти, чем сейчас есть в блоке. Поэтому количество выделений памяти и копирований будет не очень велико. А, например, в реализации DinkumWare вектор растет с коэффициентом 1.5.

Количество выделений памяти можно вообще свести к нулю, если перед заполнением вектора сделать resize или reserve.
  
Наверх
 
IP записан
 
Переключение на Главную Страницу Страницы: [1] 2 3 ... 16
ОтправитьПечать