Перевести SQL на OCL? - PullRequest
3 голосов
/ 10 июня 2010

У меня есть кусок SQL, который я хочу перевести на OCL.Я плохо разбираюсь в SQL, поэтому хочу повысить удобство обслуживания.Мы используем Interbase 2009, Delphi 2007 с разработкой Bold и modeldriven.Теперь я надеюсь, что кто-то здесь хорошо говорит на SQL и OCL :-) Оригинальный SQL:

Select Bold_Id, MessageId, ScaniaId, MessageType, MessageTime, Cancellation, ChassieNumber, UserFriendlyFormat, ReceivingOwner, Invalidated, InvalidationReason,
(Select Parcel.MCurrentStates From Parcel
Where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) as ParcelState From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and
not Exists (Select * From ScaniaEdiSolMessage EdiSolMsg
Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and EdiSolMsg.MessageType = 'IFTMBF') and
invalidated = 0 Order By MessageTime desc

После небольшого упрощения:

Select Bold_Id, (Select Parcel.MCurrentStates From Parcel 
where ScaniaEdiSolMessage.ReceivingOwner = Parcel.Bold_Id) From ScaniaEdiSolMessage
Where MessageType = 'IFTMBP' and not Exists (Select * From ScaniaEdiSolMessage
EdiSolMsg Where EdiSolMsg.ChassieNumber = ScaniaEdiSolMessage.ChassieNumber and
EdiSolMsg.ShipFromFinland = ScaniaEdiSolMessage.ShipFromFinland and 
EdiSolMsg.MessageType = 'IFTMBF') and invalidated = 0

NOTE : Есть два случая для MessageType, 'IFTMBP' и 'IFTMBF'.

Таким образом, таблица, которая должна быть указана, - ScaniaEdiSolMessage.Он имеет такие атрибуты, как:

  • Тип сообщения: Строка
  • ChassiNumber: Строка
  • ShipFromFinland: Boolean
  • Недействительно: Boolean

Он также имеет ссылку на таблицу Parcel с именем ReceivingOwner с BoldId в качестве ключа.

Так что, похоже, в нем перечислены все строки ScaniaEdiSolMessage, а затем есть подзапрос, в котором также перечислены все строки ScaniaEdiSolMessage и назван EdiSolMsg,Тогда это исключает почти все строки.Фактически, приведенный выше запрос дает одно попадание из 28000 записей.

В OCL легко перечислить все экземпляры:

ScaniaEdiSolMessage.allinstances

Также легко фильтровать строки, например, выбрав:

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)

Но я не понимаю, как мне сделать OCL, чтобы соответствовать SQL выше.

Ответы [ 3 ]

3 голосов
/ 24 января 2011

Послушайте Габриэля и Стефани, узнайте больше SQL.

Вы заявляете, что хотите сделать код более понятным, но число разработчиков, понимающих SQL, намного больше, чем число разработчиков, понимающих OCL.

Если вы выйдете из проекта завтра после преобразования его в OCL, шансы на то, что вы сможете найти кого-то, кто мог бы поддерживать OCL, очень малы. Однако шансы на то, что вы сможете найти кого-то для поддержки SQL, очень высоки.

Не пытайтесь втиснуть квадратный колышек в круглое отверстие только потому, что у вас хорошо с круглыми молотками:)

1 голос
/ 14 сентября 2012

Существует проект, Дрезден OCL , который может вам помочь.

Dresden OCL предоставляет набор инструментов для анализа и оценки ограничений OCL для различных моделей, таких как UML, EMF и Java. Кроме того, Dresden OCL предоставляет инструменты для генерации кода Java / AspectJ и SQL. Инструменты Dresden OCL могут использоваться как библиотека для другого проекта или как проект подключаемого модуля, который расширяет Eclipse с поддержкой OCL.

Я не использовал его, но есть демоверсия 1010 *, показывающая, как инструмент генерирует SQL из модели и ограничений OCL. Я понимаю, что вы просите об обратном, но, возможно, используя это, вы можете понять это. Существует также документ , который описывает преобразования OCL-> SQL теми же людьми.

0 голосов
/ 27 декабря 2017

С MDriven (преемником Bold для Delphi) я бы сделал это так:

При работе с OCL to SQL все становится проще, если вы думаете о другом наборе информации, который необходимо проверить, а затем используете операторы ocl как -> пересечение, чтобы найти нужный вам набор.

Так что в вашем случае у вас может быть такой набор:

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)

но у вас также есть такой набор:

ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP')

И еще у вас есть этот критерий:

Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages

Если все эти наборы имеют одинаковый тип результата (коллекция ScaniaEdiSolMessage), вы можете просто пересечь их, чтобы получить желаемый результат

ScaniaEdiSolMessage.allinstances->select(shipFromFinland and not invalidated)
->intersection(ScaniaEdiSolMessage.allinstances->select(m|m.ReceivingOwner.MessageType = 'IFTMBP'))
->intersection(Parcel.allinstances->select(p|p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
    )

И, глядя на это, мы можем немного уменьшить его до:

    ScaniaEdiSolMessage.allinstances
    ->select(m|m.shipFromFinland and (not m.invalidated) and
              (m.ReceivingOwner.MessageType = 'IFTMBP'))
    ->intersection(Parcel.allinstances->select(p|
             p.Messages->exists(m|m.MessageType = 'IFTMBF')).Messages
        )
...