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

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
gopstop2007
Полимат
Сообщения: 1810
Зарегистрирован: 25 Март 2009, 21:55
Благодарил (а): 24 раза
Поблагодарили: 10 раз

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

Сообщение 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
“Есть всего 2 типа языков: те, на которые все жалуются и те, которыми никто не пользуется.” — Бьерн Страуструп
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

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

Сообщение 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.

Так что этот код надо крепко чинить. Нужно описание БД и постановка задачи.
gopstop2007
Полимат
Сообщения: 1810
Зарегистрирован: 25 Март 2009, 21:55
Благодарил (а): 24 раза
Поблагодарили: 10 раз

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

Сообщение 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
“Есть всего 2 типа языков: те, на которые все жалуются и те, которыми никто не пользуется.” — Бьерн Страуструп
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8031
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

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

Сообщение Игорь Столяров »

Мне не совсем понятен код, т.к. нет описания таблиц, но сам по себе код присвоения записей:
gopstop2007 писал(а):
FileA_Rezultat:RECORD = FileA:RECORD
FileB_Rezultat:RECORD = FileB:RECORD
является рискованным, даже если записи идентичны, малейшее нарушение
последовательностей полей приведет к краху. Лучше использовать поименованное
присваивание полей внутри записи: FileA_Rezultat:RECORD :=: FileA:RECORD
Make Clarion Great Again ! 😎
Yufil
Ветеран движения
Сообщения: 1277
Зарегистрирован: 16 Май 2006, 14:34
Контактная информация:

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

Сообщение 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   
gopstop2007
Полимат
Сообщения: 1810
Зарегистрирован: 25 Март 2009, 21:55
Благодарил (а): 24 раза
Поблагодарили: 10 раз

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

Сообщение 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   
Ключ не уникальный, теперь понял :)
“Есть всего 2 типа языков: те, на которые все жалуются и те, которыми никто не пользуется.” — Бьерн Страуструп
Ответить