ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Як зробити двонаправлений запит
         

     

    Інформатика, програмування

    Як зробити двонаправлений запит

    Євген Каратаєв

    Мені давно було цікаво, чи можна зробити в Cache 'такий запит, щоб його можна було б прокручувати тому, наприклад щось на зразок команди, парної до Fetch, наприклад Prior. Власні кошти Cache 'чомусь не надають такої можливості. Для цього я вивчив характер взаємодії sql-двигуна з Cache Object Script. В результаті досліджень з'ясувалося, що це можливо, хоча і не так гладко, як би того хотілося. Сподіваюся, читач з розумінням поставиться до виниклої некрасиво.

    Візьмемо і зробимо рутину з наступним текстом:

    run ()

    & sql (declare cur CURSOR for select ID, Name, Home

    from Sample.Person order by ID asc)

    & sql (open cur)

    & sql (fetch cur)

    & sql (close cur)

    q

    Скомпіліруем і збережемо текст отриманої int-рутини. Після чого змінимо рутину наступним так:

    run ()

    & sql (declare cur CURSOR for select ID, Name, Home

    from Sample.Person order by ID desc)

    & sql (open cur)

    & sql (fetch cur)

    & sql (close cur)

    q

    І також збережемо текст отриманої int-рутини. У запиті можна використовувати будь-яку наявну у Вас таблицю, просто в даному випадку я використав таблицю з штатного дистрибутива.

    звіривши отримані тексти int-рутин. Нічого особливо романтичного у роботі автоматичного генератора не спостерігається, за винятком того, що згенеровані тексти повністю збігаються за винятком заміни операції $ o () на $ zp (), які один одному прямо протилежні за напрямком. Таким чином, для реалізації двобічної прокручування використовуємо обидва варіанти і спробуємо поєднати їх дані, залишивши та використавши коди (рутини) доступу.

    Для роботи нам будуть потрібні якісь чергові дані. Створюємо новий клас, наприклад User.NameList, спадкоємець% Persistent та% Populate. Додаємо йому нову властивість Name:% String. Зберігаємо, компіліруем. У терміналі створюємо 10 об'єктів для тесту:

    d # # class (User.NameList). Populate ()

    Запускаємо SQL Manager і для перевірки що дійсно створена таблиця sql і містить тестові дані, виконуємо запит

    select ID, Name from NameList.

    Якщо все було в порядку, то буде показана табличка з двома колонками і десятком рядків. Імена англомовні, вигадані. Для перевірки роботи прокручування в обидва боку створимо рутину (наприклад FetchBack) з кодом

    Test ()

    n ascHandle, descHandle, ascSelect, descSelect,

    n ok, i, AtEnd, Row, ID, Name, State, ascClose, descClose

    ; початкове вираз - "select ID, Name from NameList"

    ; щоб ходити по ньому, перетворимо в два

    s ascSelect = "select ID, Name from NameList order by ID ASC "

    s descSelect = "select ID, Name from NameList order by ID DESC "

    S ok = # # class (% DynamicQuery). SQLPrepare (. descHandle, descSelect)

    S ok = # # class (% DynamicQuery). SQLExecute (. descHandle)

    s descClose = descHandle

    S ok = # # class (% DynamicQuery). SQLPrepare (. ascHandle, ascSelect)

    S ok = # # class (% DynamicQuery). SQLExecute (. ascHandle)

    s State = $ li (ascHandle, 1)

    s ascClose = ascHandle

    ; йдемо на 4 кроки вперед

    s $ li (ascHandle, 1) = State

    w "4 steps forward",!

    f i = 1:1:4 d

    . d # # class (% DynamicQuery). SQLFetch (. ascHandle,. Row,. AtEnd)

    . q: (AtEnd = 1)! (Row = "")

    . s ID = $ li (Row, 1)

    . s Name = $ li (Row, 2)

    . w "ID =" _ID_ ", Name = "_Name,!

    s State = $ li (ascHandle)

    ; повертаємося на 2 кроки назад

    s $ li (descHandle, 1) = State

    w "2 steps backward",!

    f i = 1:1:2 d

    . d # # class (% DynamicQuery). SQLFetch (. descHandle,. Row,. AtEnd)

    . q: (AtEnd = 1)! (Row = "")

    . s ID = $ li (Row, 1)

    . s Name = $ li (Row, 2)

    . w "ID =" _ID_ ", Name = "_Name,!

    s State = $ li (descHandle)

    ; знову на 4 кроки вперед

    s $ li (ascHandle, 1) = State

    w "4 steps forward",!

    f i = 1:1:4 d

    . d # # class (% DynamicQuery). SQLFetch (. ascHandle,. Row,. AtEnd)

    . q: (AtEnd = 1)! (Row = "")

    . s ID = $ li (Row, 1)

    . s Name = $ li (Row, 2)

    . w "ID =" _ID_ ", Name = "_Name,!

    s State = $ li (ascHandle)

    d # # class (% DynamicQuery). SQLClose (. ascClose)

    d # # class (% DynamicQuery). SQLClose (. descClose)

    q

    Компілітуем, виконуємо. У моєму випадку це виглядає як

    USER> d Test ^ FetchBack ()

    4 steps forward

    ID = 1, Name = Presley, Samantha H.

    ID = 2, Name = Quine, Keith G.

    ID = 3, Name = Jones, Elvira A.

    ID = 4, Name = Townsend, Howard D.

    2 steps backward

    ID = 3, Name = Jones, Elvira A.

    ID = 2, Name = Quine, Keith G.

    4 steps forward

    ID = 3, Name = Jones, Elvira A.

    ID = 4, Name = Townsend, Howard D.

    ID = 5, Name = Uberoth, Juanita D.

    ID = 6, Name = Van De Griek, Michael K.

    Бачимо, що два використаних запиту гладко пошили по використовуваному стану. Це обумовлено тим, що обидва запиту абсолютно ідентичні за винятком напрямки сортування. Дослідження кодів повернення функцій дозволяє зробити судження про більш правильному відношенні до закриття запитів.

    Таким чином, скласти новий клас або набір класів, аналогічні по інтерфейсу штатним, не складає особливих проблем. За винятком того, що маючи один запит ми повинні будемо зробити з нього дві. Для цього введемо деяку некрасивість - в тілі запиту зажадаємо вказівки обох сортувань і роздільників, що обмежують власне запит і сортування. Виберемо в якості роздільник символи $ $ $ і будемо вважати, що запит будується за схемою:

    select ...

    from ...

    where ...

    $ $ $ order by ... asc

    $ $ $ order by ... desc

    І що при цьому програміст візьме на себе інтелектуальну роботу по повторення сортування в обох кінцях. Поля, що потрапляють в сортування, повинні справді визначати рядок вибірки. Якщо поля у вибірці допускають неунікальние рядки, то слід ввести поле, введення якого зробить рядок унікальною. Це потрібно для коректного зшивання сортувань. Втім, це досить поверхневе теоретичне судження і після його перевірки воно може виявитися невірним в якихось версіях.

    Все, що нам знадобиться, це утримувати в одному запиті два описувача замість одного. При створенні запиту сконструіруем два об'єкти і при виконанні операцій будемо звертатися до відповідних нашим внутрішніх об'єктів і передавати їх дані штатному sql-движку.

    Увага привертає поведінка функцій доступу, наприклад, клас% DynamicSQLQuery, функція Fetch:

    n% qref, rtn Set % qref = $ lg (qHandle, 1), rtn = $ lg (qHandle, 2)

    Quit:% qref =""!( rtn = "") $ $ $ ERROR ($ $ $ GeneralError, "Query not Prepared")

    QUIT $ $ Fetch ^ @ rtn

    Як видно по тексту, сама функція приймає і передає qHandle за посиланням, але до згенерованої рутині звертається, передаючи значення через локальні змінні. Код згенерованої рутини закритий, але судячи з того, що стан qHandle повинно бути передано назовні, її модифіковані може тільки викликається рутина $ $ Fetch ^ @ rtn. Інших проблемних моментів я не знайшов, тому до справи.

    Експортуємо класи% DynamicQuery,% DynamicSQLQuery і $ ResultSet в cdl. Доповнюємо до їх іменам символ 2 і правим коди так, щоб у% DynamicSQLQuery2 була внутрішня підтримка зворотного прокрутки, більш детальнішого Хендли, щоб у класу % DynamicQuery використовувався запит типу% DynamicSQLQuery2 і щоб клас % ResultSet2 мав ще одну функцію, що обертається до FetchBack.

    Отримані у мене для Cache '4.1.9 класи можна завантажити за посиланням в кінці сторінки.

    Перевірочний код приблизно такого вигляду:

    run ()

    n result, i

    Set result = # # class (% ResultSet2).% New ( "% DynamicQuery2: SQL")

    Do result.Prepare ( "select ID, Name from NameList

    $ $ $ order by ID ASC $ $ $ order by ID DESC ")

    Do result.Execute ()

    f i = 1:1:4 d

    . d result.Next ()

    . Write result.Get ( "ID"), result.Get ( "Name "),!

    f i = 1:1:2 d

    . d result.Prior ()

    . Write result.Get ( "ID"), result.Get ( "Name "),!

    f i = 1:1:4 d

    . d result.Next ()

    . Write result.Get ( "ID"), result.Get ( "Name "),!

    Do result.% Close ()

    q

    В внаслідок його роботи в терміналі видаються приблизно наступні дані:

    USER> d run ^ fetch ()

    1Presley, Samantha H.

    2Quine, Keith G.

    3Jones, Elvira A.

    4Townsend, Howard D.

    3Jones, Elvira A.

    2Quine, Keith G.

    3Jones, Elvira A.

    4Townsend, Howard D.

    5Uberoth, Juanita D.

    6Van De Griek, Michael K.

    Оскільки дані згенеровані випадковим чином, у Вашому випадку вони можуть виглядати інакше.

    До неприємностей методу можна віднести наступні обставини -

    Використання нестандартного набору класів

    Але що заважає змінити штатні класи, якщо це дуже потрібно?

    Використання нештатної sql конструкції

    Але штатної немає, а яка різниця, які символи будуть там написано? Адже все одно щось писати треба буде.

    В версії Cache 5 з'явився додатковий клас% ScrollableResultSet, який приблизно те ж саме і робить, і крім того об'єкт цього класу може бути збережений в базі даних. Це дозволяє просто організувати підкачки сторінок наприклад для веб інтерфейсу - видачу строк порціями із збереженням контексту запиту між зверненнями до бази наприклад.

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://karataev.nm.ru/

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status