Страница 1 из 1

Relation - копирование связаных файлов

Добавлено: 02 Июль 2015, 20:39
gopstop2007
Пришлось столкнуться с "вырезанием" связанных FileA и FileB (1:M) файлов данных по условию (Например: MyDate - Дата ) с последующим сохранением в результирующие файлы FileA_Rezultat и FileB_Rezultat, давно не сталкивался, боюсь ошибиться :) Может есть более быстрый и результативный код?

Код: Выделить всё

Relate:FileA.SetQuickScan(1,Propagate:OneMany) !enable quickscan for 1:Many
Relate:FileB.SetQuickScan(1)                     !enable quickscan for primary

STREAM(FileA_Rezultat); STREAM(FileB_Rezultat)
LOGOUT(1,FileA,FileB)
SET(FileA)
LOOP
    NEXT(FileA); IF ERRORCODE() THEN BREAK END
    IF FileA.Date < MyDate THEN CYCLE END
    FileA_Rezultat:RECORD = FileA:RECORD
    Add(FileA_Rezultat); IF ERRORCODE() THEN STOP(ERROR()); ROLLBACK END
    FileB.PrimariField = FileA.PrimariField
    SET(FileB.PrimariKey,FileB.PrimariKey)
    LOOP
        NEXT(FileB); IF ERRORCODE() THEN BREAK END
        IF FileB.PrimariField <> FileA.PrimariField THEN CYCLE END
        FileB_Rezultat:RECORD = FileB:RECORD
        Add(FileB_Rezultat); IF ERRORCODE() THEN STOP(ERROR()); ROLLBACK END        
    END    
END    
COMMIT

FLUSH(FileA_Rezultat); FLUSH(FileB_Rezultat)
Relate:FileB.SetQuickScan(0)                     !disable quickscan for primary

Relation - копирование связаных файлов

Добавлено: 02 Июль 2015, 22:34
Yufil
1. Сказал ABC - значит, ABC

Код: Выделить всё

     Set(FileA) 
     LOOP While(~Access:FileA.Next() )
     ....
     END 
2. Нафиг Logout/Rollback/Commit, если FileA и FileB не пишутся. Эти операторы уместны для копий, а для первичных смысла не имеют.

3. Структура ключей PrimaryKey неизвестна, но

Код: Выделить всё

   FileB.PrimariField = FileA.PrimariField
    SET(FileB.PrimariKey,FileB.PrimariKey)
намекает, что отношение 1:1. Если 1:M то, как минимум, уместно

Код: Выделить всё

Clear(FileB:Record)
перед присваиванием

4.

Код: Выделить всё

    IF FileB.PrimariField <> FileA.PrimariField THEN CYCLE END
Это приводит к просмотру ВСЕХ записей FileB с ключом больше, чем FileA.

Так что этот код надо крепко чинить. Нужно описание БД и постановка задачи.

Relation - копирование связаных файлов

Добавлено: 03 Июль 2015, 0:18
gopstop2007
Спасибо Юрий за замечания :) Исправил, некоторые были допущены по невнимательности, спасибо что поправили. Может еще кто-то добавит свои 5 копеек :)

Код: Выделить всё

Relate:FileA.SetQuickScan(1,Propagate:OneMany) !enable quickscan for 1:Many
Relate:FileB.SetQuickScan(1)                     !enable quickscan for primary

STREAM(FileA_Rezultat); STREAM(FileB_Rezultat)
LOGOUT(1,FileA_Rezultat,FileB_Rezultat)
SET(FileA)
LOOP While(~Access:FileA.Next() )
    IF FileA.Date < MyDate THEN CYCLE END
    FileA_Rezultat:RECORD = FileA:RECORD
    Add(FileA_Rezultat); IF ERRORCODE() THEN STOP(ERROR()); ROLLBACK END
    FileB.PrimariField = FileA.PrimariField    ! стать на первую запись для дальнейшего цикла FileB 
    SET(FileB.PrimariKey,FileB.PrimariKey)
    LOOP While(~Access:FileB.Next() )
         IF FileB.PrimariField <> FileA.PrimariField THEN BREAK END
         FileB_Rezultat:RECORD = FileB:RECORD
         Add(FileB_Rezultat); IF ERRORCODE() THEN STOP(ERROR()); ROLLBACK END       
    END   
END   
COMMIT

FLUSH(FileA_Rezultat); FLUSH(FileB_Rezultat)
Relate:FileB.SetQuickScan(0)                     !disable quickscan for primary

Relation - копирование связаных файлов

Добавлено: 03 Июль 2015, 6:16
Игорь Столяров
Мне не совсем понятен код, т.к. нет описания таблиц, но сам по себе код присвоения записей:
gopstop2007 писал(а):
FileA_Rezultat:RECORD = FileA:RECORD
FileB_Rezultat:RECORD = FileB:RECORD
является рискованным, даже если записи идентичны, малейшее нарушение
последовательностей полей приведет к краху. Лучше использовать поименованное
присваивание полей внутри записи: FileA_Rezultat:RECORD :=: FileA:RECORD

Relation - копирование связаных файлов

Добавлено: 03 Июль 2015, 10:02
Yufil
Вот этот кусок сомнителен. Если PrimaryKey - уникальный ключ по PrimaryField, то не нужен цикл,

FileB.PrimariField = FileA.PrimariField ! стать на первую запись для дальнейшего цикла FileB
IF ~Access:FileB.Fetch(FileB.PrimaryKey)
....
END

а если неуникальный, то нужно Clear на остальные поля ключа

Код: Выделить всё

    Clear(FileB.Record) 
    FileB.PrimariField = FileA.PrimariField    ! стать на первую запись для дальнейшего цикла FileB 
    SET(FileB.PrimariKey,FileB.PrimariKey)
    LOOP While(~Access:FileB.Next() )
         .... 
    END   

Relation - копирование связаных файлов

Добавлено: 03 Июль 2015, 12:51
gopstop2007
Игорь Столяров писал(а):... является рискованным, даже если записи идентичны, малейшее нарушение
последовательностей полей приведет к краху. Лучше использовать поименованное
присваивание полей внутри записи: FileA_Rezultat:RECORD :=: FileA:RECORD
Спасибо за замечание
Yufil писал(а):Вот этот кусок сомнителен. Если PrimaryKey - уникальный ключ по PrimaryField, то не нужен цикл,

FileB.PrimariField = FileA.PrimariField ! стать на первую запись для дальнейшего цикла FileB
IF ~Access:FileB.Fetch(FileB.PrimaryKey)
....
END

а если неуникальный, то нужно Clear на остальные поля ключа

Код: Выделить всё

    Clear(FileB.Record) 
    FileB.PrimariField = FileA.PrimariField    ! стать на первую запись для дальнейшего цикла FileB 
    SET(FileB.PrimariKey,FileB.PrimariKey)
    LOOP While(~Access:FileB.Next() )
         .... 
    END   
Ключ не уникальный, теперь понял :)