|
|
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Доброго времени суток! Нашел на этом сайте статью на тему подключения к бтривовским файлам из Дельфи. Для прямого подключения к базе с использованием Btrieve API необходимо расписать в программе структуру таблицы (добавляется тип record с полями, соответствующими названиям полей в таблице). При этом размеры и типы полей должны точно соответствовать (например, unsigned int, 4 byte (в таблице) -> longword (Дельфи)). Так вот, одну таблицу, где "нормальные" типы полей, я смог открыть, все замечательно. Но в другой есть поле типа, который называемый "COBOL Decimal Comp-3", длиной 3 байта... Слово Decimal явно говорит о том, что тип - числовой. Но числового типа длиной 3 байта в Delphi нет. Позволяет ли Дельфи как-то обойти такую ситуацию? Добавить свой вещественный тип? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.08.2005, 15:37 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Это упакованный с фиксированной десятичной точкой - каждая цифра 0-9 занимает полбайта, последний полубайт - знак числа - 16-чные A?,С,E?,F = + (положительное),B?,D = - (отрицательное) (там где вопросики я не уверен). Положение десятичной точки в самом числе не хранится. Таким образом в 3 байтах 3*2-1 = 7 значное число. Но это может быть любое: 7,0 7,1 ... 7,7. В стандартном Delphi до 5 версии аналогов не было, но были стороние библиотеки. Это один из числовых форматов EDBSCI или EBDSCI (или както похоже - точно не помню) разработанный еще для HAVI METAL (IBM 360/380). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.08.2005, 07:07 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Спасибо. Я, оказывается, выход нашел сразу, описал это поле как array [0..2] of char (значение этого поля меня не интересует). Но таблица не открывалась не по этой причине. Я выгружал таблицу docdep.dat (2Гб) (кто знает - это балансовые проводки в АБС-ке Diasoft Card). Так вот, открыть этот файл невозможно, если рядом с ним не лежит файл docdep.^01 (еще 400 метров :)). Кто-нибудь подскажет, что это за файл и нафига он нужен? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.08.2005, 08:51 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
В Btrieve таблицы не зависимы в том плане что нет запрета что-то читать отдельно - скорее всего ты натыкаешься на другие ограничения - например длину файла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 08:45 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
golsaВ Btrieve таблицы не зависимы в том плане что нет запрета что-то читать отдельно - скорее всего ты натыкаешься на другие ограничения - например длину файла. Да, так и есть, файл оказался продолжением того же docdep-a. Осталась вроде последняя проблема. Btrieve позволяет искать записи только по тем полям, которые описаны в индексах. Я в программе использую для выборки записей функцию BTRVID. Так вот, на таблице есть несколько индексов: несколько по одному полю, и несколько составных. По индексам из одного поля ищет нормально, а по составному просто возвращает первую запись в файле. В чем тут может быть загвоздка? Вот фрагмент кода: ... //присваем значение индекса DocdepIndex0.datetrf := 73777; DocdepIndex0.crncode:=840; DocdepIndex0.batch:=1; DocdepIndex0.doctype:=#1; DocdepIndex0.ddp_auto:=2120656; ... fillchar(DocdepRecord , SizeOf(DocdepRecord), #0); dataLen := sizeof(Docdep_STRUCT); //Дальше вызов функции BTRVID: status := BTRVID(B_GET_FIRST, PosBlock, DocdepRecord, dataLen, DocdepIndex0, 0, client); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 09:55 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Строку fillchar(DocdepRecord , SizeOf(DocdepRecord), #0); попробуй перенести выше - перед присвоением значений структуре DocdepRecord. Перед чтением установи индекс (должна быть специальная функция-команда что-то типа B_SET_INDEX) по которому будет поиск. Индексы не имеют имен, они нумеруются в порядке создания - вот только с 0 или 1 - точно не помню (кажется все же с 0). Функции передается номер индекса. Если запустить утилиту BUTIL -STAT <имя файла> получишь список индексов в порядке их создания. Или посмотреть в DDF файлах - номер там присутствует. B_GET_FIRST - чтение первой записи, если индекс не уникальный следующие записи читать B_GET_NEXT (должно быть както так) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 10:45 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Про строку в предыдущем посте я зря. Не могли бы вы послать на gol-sa@mail.ru файлики из Pervasive SQL SDK для Delphi. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 11:36 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
golsaПро строку в предыдущем посте я зря. Не могли бы вы послать на gol-sa@mail.ru файлики из Pervasive SQL SDK для Delphi. Издевается. Зайдите на pervasive.com там есть куча всяких библиотек для разработчиков чего только не упомнишь. А здесь если не ошибаюсь куча всяких ddf эдиторов. Pervasive это контора которая в свое время купила btrieve у новела ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 12:45 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Номер и структуру индекса я посмотрел как раз в DDF - это 0-й индекс (номер указан в предпоследнем параметре BTRVID). Причем DDF этот рабочий, т.е. верно отражает структуру таблицы (он используется давно для подключения через ODBC). "Перед чтением установи индекс (должна быть специальная функция-команда что-то типа B_SET_INDEX) по которому будет поиск. " Попробую покопаться еще, но навскидку в хелпе и *.pas файлах из SDK ничего подобного не вижу... Файлики сейчас Вам вышлю, возможно, Вы вспомните? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.08.2005, 14:22 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Я email написал неправильно - надо gol_sa@mail.ru Посмотри еще на RECORD для индекса - там может надо отменить выравнивание - PACKED RECORD. В строковых переменных вполне возможно надо расширять до полной длины пробелами. В зависимости от типа в BTRIEVE строковые переменные иногда приходится заменять на массивы типа CHAR (без байта длины в начале и без 0 в конце). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 07:21 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
У меня все строковые поля так и объявлены: array [0..n] of char. Packed попробовал убрать, не помогает. Процесс начинает напоминать танцы с бубном вокруг Btrieve. Вот, пока писал, пришла в голову мысль, что наверняка надо заполнять все поля в индексе? Я-то так и делаю, но в общем случае совсем неудобно получается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 08:38 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
При точном (B_GET_EQUAL) поиске надо заполнять все поля. Для команд B_GET_LESS (меньше) и B_GET_GREATER (больше) можно только по старшим полям индекса (любое кол-во полей с начала RECORDа без перерыва, остальные до конца RECORDа для стабильного результата затереть $0). Данные, которые передаются в BTRVID() больше никак не преобразуются, поэтому надо точно знать как их заполнять. Возьми любой 16-чный вьюер и рассмотри свой файл - найди там какую-нибудь запись. Вычлени поля индекса. Потом заполни данными свой RECORD и посмотри на его 16-ричный образ (можешь в файл записать). Образ должен один в один совпадать с полями индекса выбранными из записи. Учти в чистом BTRIEVE индекс может строится не по целым полям - просто там для индекса задается массив смешений от начала записи и длин (могут даже пересекаться!). Но к Pervasive SQL это не относится - в DDF индексы описываются только полями. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 09:52 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Блин, у меня складывается впечатление, что Pervasive на индекс при поиске вообще не обращает внимания. Я ему четко указал: DocdepIndex0.crncode:=840; В результате он находит строку (BTRVID<>B_KEY_VALUE_NOT_FOUND), но в ней crncode=810! DocdepIndex0.crncode:=840; DocdepIndex0.datetrf := $0; DocdepIndex0.batch:=$0; //строка DocdepIndex0.doctype:=#0; DocdepIndex0.ddp_auto:=$0; fillchar(DocdepRecord , SizeOf(DocdepRecord), #0); dataLen := sizeof(Docdep_STRUCT); status := BTRVID(B_GET_FIRST, {системная константа} PosBlock, {системная} DocdepRecord, {сюда будет возвращен результат поиска} dataLen, {см.выше} DocdepIndex0, {см.выше} 0, {номер индеска - см.выше} client); {системная} //А выводит '0 810' if status<>B_KEY_VALUE_NOT_FOUND then showmessage(inttostr(status)+' '+floattostr(docdeprecord.crncode)) else showmessage('Не найдено'); ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 12:14 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Только команды B_GET_EQUAL,B_GET_LESS,B_GET_GREATER или разновидности двух последних (не знаю как называются константы) меньше или равно B_GET_LESS_OR_EQUAL? и больше или равно B_GET_GREATER_OR_EQUAL? используют значения DocdepIndex0 для позиционирования. Команда B_GET_FIRST - дать первую запись файла в сортировке по индексу! Т.е. это начало последовательного чтения файла по индексу. Более подробно см http://emanual.ru/download2/2172.html#CONTENTS глава 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 12:57 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Если в том же вызове BTRVID B_GET_FIRST заменить на B_GET_GE (GREATER OR EQUAL), BTRVID возвращает 2 (IO Error). Ничего не понимаю: записи с crncode>840 точно есть (код валюты 978 - евро) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 31.08.2005, 15:18 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Тогда скорее всего структура индекса не соответствует DocdepIndex0. Или попробуй номер индекса = 1 (вдруг с 1 нумерация). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2005, 09:11 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
golsa... попробуй номер индекса = 1 (вдруг с 1 нумерация). Эврика! Я-то ориентировался на DDF, считая, что там должна быть абсолютно точно расписана структура таблица, включая индексы. А на самом деле получается, что нулевой индекс в ДДФ-е пропущен. Т.е. в DDF на месте 0-го индекса стоит 1-ый, по которому я и пытался сделать поиск. Спасибо за помощь! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2005, 17:54 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Все-таки проблемы не кончились. Когда в программе я нахожу по индексу первую запись, далее начинаю в цикле выбирать все записи, удовлетворяющие заданному условию. Так вот, после нескольких сот итераций (записей) снова вываливается статус=2 (IO_Error) (причем для конкретного условия при каждом запуске нормально выбирается одно и то же число записей). Не могу понять, что ему нужно на этот раз. //условие поиска DocdepIndex8.datetrf:=74726; DocdepIndex8.mainddp_auto:=$0; DocdepIndex8.conv_auto:=$0; //находим первую строку fillchar(DocdepRecord , SizeOf(DocdepRecord), #0); dataLen := sizeof(Docdep_STRUCT); status := BTRVID(B_GET_GE, PosBlock, DocdepRecord, dataLen, DocdepIndex8, 8, client); //просматриваем все записи, удовлетворяющие условию поиска while (status=B_NO_ERROR) and (status<>9) and (docdeprecord.datetrf=74726) do begin fillchar(DocdepRecord , SizeOf(DocdepRecord), #0); dataLen := sizeof(Docdep_STRUCT); status := BTRVID(B_GET_NEXT,PosBlock,DocdepRecord, dataLen, DocdepIndex8, 8, client); label1.Caption:=inttostr(i); label2.Caption:=inttostr(status); application.ProcessMessages; i:=i+1; end; ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.09.2005, 19:45 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Внешне код нормальный - погляди данные не длинее они заказаного в dataLen? (у Btrieve могут быть записи переменной длины), выведи значение dataLen после BTRVID() - он не меняется? может индекс битый? или сам файл? Или каким-то образом портятся данные в структуре PosBlock? В ней хранится информация о позиции текущей записи в файле (т.е. меняется при каждом BTRVID()), которая используется командой B_GET_NEXT. Сделай с помощью утилиты BUTIL (см. в каталоге BIN Pervasive) выгрузку данных (-SAVE), потом создание нового файла по шаблону (-CLONE) и загрузку в него данных (-LOAD). Индексы перестроятся, заодно полюбуешься на текстовый файл выгруженных данных. Попробуй отыскать запись, на которой сваливается программа. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2005, 06:31 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
При 2-ой ошибке нужно базу лечить однозначно. Пользуйся компонентами из PDAC Pervasive , ими можно как SQL запросами так и прямым доступом к таблице пользоваться, тем более что в PSQL v9 значичельно расширены возможности SQL, вплоть до встроенных функций. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2005, 12:33 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
RAndrey Так вот, одну таблицу, где "нормальные" типы полей, я смог открыть, все замечательно. Но в другой есть поле типа, который называемый "COBOL Decimal Comp-3", длиной 3 байта... Слово Decimal явно говорит о том, что тип - числовой. Но числового типа длиной 3 байта в Delphi нет. Позволяет ли Дельфи как-то обойти такую ситуацию? Добавить свой вещественный тип? А я столкнулась с таким типом данных Btrieve, как Money. Подбирала какой это тип данных в Делфи, подошел только Extended, т.е. если полю с типом Money я в описании структуры файла задаю Extended, то он записи выбирает нормально, НО в это поле попадают какие-то бешеные цифры абсолютно не соотв. действительности... Как с этим бороться не знаю :-((( ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2005, 12:41 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
3 раза ответил ничего не уходит. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 02.09.2005, 13:31 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
2 Len@ Extended подошел только потому что он занимает - 8 байт!, см. мой ответ на этот вопрос - это 15 значное десятичное в копейках (центах) со знаком. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.09.2005, 06:56 |
|
||
|
Взаимодействие с Btrieve из Delphi
|
|||
|---|---|---|---|
|
#18+
Money = decimal(15,2) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.09.2005, 06:59 |
|
||
|
|

start [/forum/topic.php?fid=56&msg=33250615&tid=2016573]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
72ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
51ms |
get tp. blocked users: |
1ms |
| others: | 229ms |
| total: | 396ms |

| 0 / 0 |
