//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System.Diagnostics; using System.Globalization; using System.Text; using Microsoft.Isam.Esent.Interop.Windows8; /// /// Base class for enumerators that return IndexInfo objects. Subclasses differ /// by how they open the table. /// internal abstract class IndexInfoEnumerator : TableEnumerator { /// /// Initializes a new instance of the class. /// /// /// The session to use. /// protected IndexInfoEnumerator(JET_SESID sesid) : base(sesid) { } /// /// Gets or sets the indexlist used to retrieve data. /// protected JET_INDEXLIST Indexlist { get; set; } /// /// Gets the entry the cursor is currently positioned on. /// /// The entry the cursor is currently positioned on. protected override IndexInfo GetCurrent() { return this.GetIndexInfoFromIndexlist(this.Sesid, this.Indexlist); } /// /// Retrieves information about indexes on a table. /// /// The session to use. /// The name of the index. /// Filled in with information about indexes on the table. /// The type of information to retrieve. protected abstract void GetIndexInfo( JET_SESID sesid, string indexname, out string result, JET_IdxInfo infoLevel); /// /// Create an array of IndexSegment objects from the data in the current JET_INDEXLIST entry. /// /// The session to use. /// The indexlist to take the data from. /// An array of IndexSegment objects containing the information for the current index. private static IndexSegment[] GetIndexSegmentsFromIndexlist(JET_SESID sesid, JET_INDEXLIST indexlist) { var numSegments = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcColumn); Debug.Assert(numSegments > 0, "Index has zero index segments"); // If we use the wide API (Vista+), then the temp table will be in UTF-16. Encoding encodingOfTextColumns = EsentVersion.SupportsVistaFeatures ? Encoding.Unicode : LibraryHelpers.EncodingASCII; var segments = new IndexSegment[numSegments]; for (int i = 0; i < numSegments; ++i) { string columnName = Api.RetrieveColumnAsString( sesid, indexlist.tableid, indexlist.columnidcolumnname, encodingOfTextColumns, RetrieveColumnGrbit.None); columnName = StringCache.TryToIntern(columnName); var coltyp = (JET_coltyp)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcoltyp); var grbit = (IndexKeyGrbit)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidgrbitColumn); bool isAscending = IndexKeyGrbit.Ascending == grbit; var cp = (JET_CP)Api.RetrieveColumnAsInt16(sesid, indexlist.tableid, indexlist.columnidCp); bool isASCII = JET_CP.ASCII == cp; segments[i] = new IndexSegment(columnName, coltyp, isAscending, isASCII); if (i < numSegments - 1) { Api.JetMove(sesid, indexlist.tableid, JET_Move.Next, MoveGrbit.None); } } return segments; } /// /// Create an IndexInfo object from the data in the current JET_INDEXLIST entry. /// /// The session to use. /// The indexlist to take the data from. /// An IndexInfo object containing the information from that record. private IndexInfo GetIndexInfoFromIndexlist(JET_SESID sesid, JET_INDEXLIST indexlist) { // If we use the wide API (Vista+), then the temp table will be in UTF-16. Encoding encodingOfTextColumns = EsentVersion.SupportsVistaFeatures ? Encoding.Unicode : LibraryHelpers.EncodingASCII; string name = Api.RetrieveColumnAsString( sesid, indexlist.tableid, indexlist.columnidindexname, encodingOfTextColumns, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); CultureInfo cultureInfo = null; if (EsentVersion.SupportsWindows8Features) { string localeName; this.GetIndexInfo(sesid, name, out localeName, Windows8IdxInfo.LocaleName); cultureInfo = new CultureInfo(localeName); } else { #if !MANAGEDESENT_ON_CORECLR // This probably won't work on platforms that don't support LCIDs. Newer environments have dropped // LCIDs in favour of locale names. But currently JET_INDEXLIST doesn't expose columnidLocale. int lcid = (int)Api.RetrieveColumnAsInt16(sesid, indexlist.tableid, indexlist.columnidLangid); cultureInfo = LibraryHelpers.CreateCultureInfoByLcid(lcid); #endif // !MANAGEDESENT_ON_CORECLR } uint lcmapFlags = (uint)Api.RetrieveColumnAsUInt32(sesid, indexlist.tableid, indexlist.columnidLCMapFlags); CompareOptions compareOptions = Conversions.CompareOptionsFromLCMapFlags(lcmapFlags); uint grbit = (uint)Api.RetrieveColumnAsUInt32(sesid, indexlist.tableid, indexlist.columnidgrbitIndex); int keys = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcKey); int entries = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcEntry); int pages = (int)Api.RetrieveColumnAsInt32(sesid, indexlist.tableid, indexlist.columnidcPage); IndexSegment[] segments = GetIndexSegmentsFromIndexlist(sesid, indexlist); return new IndexInfo( name, cultureInfo, compareOptions, segments, (CreateIndexGrbit)grbit, keys, entries, pages); } } }