Мир InterBase

Чтение метаданных


Помимо управления транзакциями, сессия предоставляет еще одну полезную возможность - получение метаданных для базы данных (о метаданных см. главу "Структура базы данных InterBase" (ч. 4)). Поскольку в некоторых системах, например в Microsoft Distributed Query, операция получения метаданных выполняется очень часто, то IBProvider хранит информацию о них в оперативной памяти (т. е. кеширует). Кэширование метаданных можно настраивать для обеспечения оптимального быстродействия. Определить режим кеширования можно через свойство инициализации источника данных "schema_cache" и свойство сессии - "Session Schema Cache". Этим свойствам можно присваивать следующие значения:

  • Кэширование запрещено. Данные будут всегда перечитываться.
  • Глобальное кеширование на уровне Data Source. Это режим по умолчанию.
  • Кеширование на уровне Session.
  • Если при запросе метаданных сессия содержит явно запущенную транзакцию, то провайдер не будет использовать дополнительную внутреннюю транзакцию для получения данных, а воспользуется уже существующей. Если явно запущенной транзакции нет, то IBProvider автоматически запустит внутреннюю транзакцию с уровнем изоляции, указанной в свойстве сессии "Autocommit Isolation Levels". Для запрещения автоматического запуска провайдером внутренних транзакций для извлечения метаданные необходимо определить в строке инициализации источника данных "inner_trans=false" или установить свойство сессии "Session InnerTrans=false".

    Получение и вывод списка таблиц базы данных:

    ADODB

    Dim cn As New ADODB.Connection

    Call cn.Open("file name=d:\database\employee.ibp")

    Dim rs As ADODB.Recordset

    Set rs = cn.OpenSchema(adSchemaTables)

    Cells.Clear

    Dim col As Long, row As Long



    row = 1

    'печать названия колоник

    For col = 0 To rs.Fields.Count - 1

    Cells(row, col + 1) = rs(col).Name

    Next col

    'печать содержимого

    While Not rs.EOF

    row = row + 1

    For col = 0 To rs.Fields.Count - 1

    Cellsfrow, col + 1) = rs(col).Value


    Next col

    rs.MoveNext

    Wend

    Здесь следует обратить внимание на одну особенность. Спецификация OLE DB для некоторых полей таблиц метаданных определяет типы, несовместимые с VARIANT, например UI8. Поэтому при попытке получения значения из этих полей через ADODB может возникнуть ошибка;

    C++

    try

    {

    t_db_data_source сn;

    _THROW_OLEDB_FAILED(cn,attach("file

    name=d:\\database\\employee.ibp"));

    t_db_session session;

    _THROW_OLEDB_FAILED(session,create(сn));

    //библиотека напрямую не поддерживает

    //работу с интерфейсом получения

    //наборов информационной схемы,

    //поэтому напишем необходимый код "в лоб".

    IDBSchemaRowsetPtr spSR(session.session_obj());

    if(!spSR)

    t_ole_error::throw_error(

    "query interface [IDBSchemaRowset]",spSR.m_hr);

    IUnknownPtr spUnk;

    HRESULT hr=spSR->GetRowset(NULL,DBSCHEMA_TABLES,0,NULL,

    IID_IUnknown,0,NULL,&spUnk.ref_ptr());

    if(FAILED(hr))

    t_ole_error::throw_disp_error(hr,"get tables list");

    //подключаем полученный набор к курсору

    t_db_cursor cursor;

    _THROW_OLEDB_FAILED(cursor,attach(spUnk))

    //получаем описание полей результирующего

    //множества (набора данных)

    t_db_row row;

    _THROW_OLEDB_FAILED(cursor,describe(row))

    //печатаем содержимое набора

    while(cursor.fetch(row)==S_OK)

    {

    for(t_db_row::size_type i=0;i!=row.count;++i)

    cout<<row.columns(i).name<<":"<<row[i].as_string<<endl ;

    cout<<endl;

    }//while

    //проверяем причину выхода из цикла

    _THROW_OLEDB_FAILED(cursor,m_last_result)

    }

    catch(const exception& exc){

    cout<<"error:"<<exc.what()<<endl;

    }


    Содержание раздела