Форум » [x]Harbour » Как определить неправильный индекс » Ответить

Как определить неправильный индекс

Pasha: Предложите алгоритм определения битого индекса Я пока сделал так: 1 Цикл по всем записям: for i := 1 to RecCount() goto i if ordKeyNo() == 0 // битый ключ endif next 2. Сделать go top/go bottom Если таблица непустая, а результат этих операций bof() или eof(), то индекс битый Какой способ можно предложить еще ?

Ответов - 12

AndreyZh: У меня проверяется так: (выделю жирным основные моменты) [pre] * --------------------------------------------------------------------------- * Выборочная проверка физической и логической целостности данных пакета. * Все базы закрываются, а после проверки открываются заново. STAT PROC pCheck() LOCA aBas:={ {cDbase,"Wares", {"WarCode"}},; {cDbase,"Cash_ord", {"CashCode"}},; {cDbase,"ClearWar", {"Cw_code"}},; {cDbase,"Invoices", {"InvCode"}},; {cDbase,"Receipts", {"RecCode"}},; {cDbase,"Stores", {"Stor_war"}} } LOCA nI:=0, nJ:=0, lCheck:=TRUE, lExit:=FALSE LOCA sOp:="9105" S_PROC pinStat(sOp,0) CLOS DATA SET CURS OFF FOR nI := 1 TO Len( aBas ) // По базам. FOR nJ := 1 TO Len( aBas[nI,3] ) // По индексам. pOpenView( cHelpc, cError, "База данных: "+aBas[nI,2]+" Индекс: "+aBas[nI,3,nJ] ) lCheck := lIndCheck( aBas[nI,1]+aBas[nI,2], aBas[nI,1]+aBas[nI,3,nJ] ) pCloseView() IF !lCheck IF !Fyn("Обнаружено разрушение индекса "+aBas[nI,3,nJ]+" в базе "+aBas[nI,2]+". Продолжать?", cError) lExit := TRUE ENDI ENDI IF lExit THEN EXIT NEXT nJ IF lExit THEN EXIT NEXT nI // Стираю файл выхода по ошибке. Ferase("LS_WORKS.DBF") fErrQuit("Извините, но после этой операции я должна закончить работу!",cMainc) RETU * --------------------------------------------------------------------------- * Функция проверки физической целостности одного индексного файла. STAT FUNC lIndCheck( cDbf, cNtx ) LOCA nOldSel:=Select(), nInd:=IndexOrd(), nRec:=RecNo() LOCA nI:=0, lClose:=FALSE, xRes:=NIL, xOld:=NIL, cKey:="", nC:=0 USE (cDbf) INDE (cNtx) SHAR READONLY IF NetErr() THEN RETU FALSE // Проверяем целостность порядка индексации. cKey := IndexKey() nC := LastRec() DbGoTop() xRes := xOld := Eval( &("{||"+cKey+"}") ) nI := 0 DO WHIL !Eof() IF Inkey() == K_ESC THEN RETU FALSE pChangeView( zInt(++nI*100/nC) ) xOld := Eval( &("{||"+cKey+"}") ) IF xRes > xOld DbCloseArea(); RETU FALSE ENDI xRes := xOld DbSkip() ENDD DbCloseArea() RETU TRUE [/pre]

Pasha: Т.е, проверка заключается в том, что ключи проверяются на возрастание На больших таблицах это тоже будет очень медленно. Есть еще очень быстрый способ: После открытия индекса сразу проверить количество ключей: if RecCount() > OrdKeyCount() // bad index endif Что можно предложить еще ?

Dima: Pasha пишет: if RecCount() > OrdKeyCount() Если индекс уникальный это не сработает правильно


petr707: // поиск вычисленных ключей - по всем записям set order to nind block := &("{||"+indexkey()+"}") .. lerr:=.f. set order to 0 go top do while !eof() ckey:= eval(block) recn:=recno() set order to nind dbseek(ckey,.f.) lerr:=.t. do while !eof().and.(ckey==eval(block)) if recno()=recn lerr:=.f.; EXIT endif skip enddo if lerr// bad index exit endif set order to 0 go recn skip enddo ...

Pasha: Всем спасибо. В результате я остановился на примерно таком алгоритме: [pre]Local bKey := &('{||'+IndexKey()+'}') Local cFor := OrdFor(), bFor Local lUniq := ordIsUnique() Local lBad := .f., i if ! Empty(cFor) bFor := &('{||'+cFor+'}') endif // быстрая проверка для неуникального индекса if ! lUniq .and. Empty(cFor) .and. OrdKeyCount() < RecCount() lBad := .t. endif set deleted off // еще одна быстрая проверка if ! lBad .and. Empty(cFor) .and. RecCount() > 0 go bottom if eof() lBad := .t. endif endif // если не судьба, приходится проверять весь файл: if ! lBad for i := 1 to RecCount() goto i if Empty(bFor) .or. Eval(bFor) if ! (Eval(bKey) == OrdKeyVal()) lBad := .t. exit endif elseif OrdKeyVal() != nil lBad := .t. exit endif next endif[/pre]

Andrey: Вот еще один залет на индексе (открываю базу, потом индексный файл) и ошибка вообще не знамо где: По коду своему без толку лазить, ничего не найдешь. Вынос мозга и все.... Кому интересно, пример базы и индекс здесь - https://cloud.mail.ru/public/56155cb9fec5/MiniGui-Sample

Dima: как обычно накосячил.

Andrey: Dima пишет: как обычно накосячил. Индекс слетел сам, по вылету программы, а потом драйвер DBF открывает его, без обработки на ошибку. Ну и где я накосячил ?

Dima: Andrey Андрей а если сделать простую программу без GUI , типа: открыл базу затем browse() будут какие то ошибки или она просто тихо завершится ?

Andrey: Dima пишет: открыл базу затем browse() будут какие то ошибки или она просто тихо завершится ? Пробовал dbedit - все работает без вылета. На экране записей нет и всё. Вылета нет.

Dima: Andrey пишет: На экране записей нет и всё А по факту записи есть в базе ?

Andrey: Да, есть. Но терминалка работает, записей нет и все, т.е. прога (терминалка) не вылетает. Я написал про МиниГуи другим на заметку. Что вылет происходит при "битых" индексах.



полная версия страницы