/// <summary> /// Create an array of IndexSegment objects from the data in the current JET_INDEXLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="indexlist">The indexlist to take the data from.</param> /// <returns>An array of IndexSegment objects containing the information for the current index.</returns> 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"); var segments = new IndexSegment[numSegments]; for (int i = 0; i < numSegments; ++i) { string columnName = Api.RetrieveColumnAsString( sesid, indexlist.tableid, indexlist.columnidcolumnname, NativeMethods.Encoding, 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); }
/// <summary> /// Create a ColumnInfo object from the data in the current JET_COLUMNLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="columnlist">The columnlist to take the data from.</param> /// <returns>A ColumnInfo object containing the information from that record.</returns> private static ColumnInfo GetColumnInfoFromColumnlist(JET_SESID sesid, JET_COLUMNLIST columnlist) { string name = Api.RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, NativeMethods.Encoding, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var coltypValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcoltyp); uint codepageValue = (ushort)Api.RetrieveColumnAsUInt16(sesid, columnlist.tableid, columnlist.columnidCp); var maxLength = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcbMax); byte[] defaultValue = Api.RetrieveColumn(sesid, columnlist.tableid, columnlist.columnidDefault); var grbitValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidgrbit); return(new ColumnInfo( name, new JET_COLUMNID { Value = columnidValue }, (JET_coltyp)coltypValue, (JET_CP)codepageValue, checked ((int)maxLength), defaultValue, (ColumndefGrbit)grbitValue)); }
/// <summary> /// Create an IndexInfo object from the data in the current JET_INDEXLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="indexlist">The indexlist to take the data from.</param> /// <returns>An IndexInfo object containing the information from that record.</returns> private static IndexInfo GetIndexInfoFromIndexlist(JET_SESID sesid, JET_INDEXLIST indexlist) { string name = Api.RetrieveColumnAsString( sesid, indexlist.tableid, indexlist.columnidindexname, NativeMethods.Encoding, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); int lcid = (int)Api.RetrieveColumnAsInt16(sesid, indexlist.tableid, indexlist.columnidLangid); var cultureInfo = new CultureInfo(lcid); 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)); }
/// <summary> /// Create a ColumnInfo object from the data in the current JET_COLUMNLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="columnlist">The columnlist to take the data from.</param> /// <returns>A ColumnInfo object containing the information from that record.</returns> private static ColumnInfo GetColumnInfoFromColumnlist(JET_SESID sesid, JET_COLUMNLIST columnlist) { // As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have // worked in Win7, it wasn't reliable until Win8. Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII; string name = Api.RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, encodingOfTextColumns, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var coltypValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcoltyp); uint codepageValue = (ushort)Api.RetrieveColumnAsUInt16(sesid, columnlist.tableid, columnlist.columnidCp); var maxLength = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcbMax); byte[] defaultValue = Api.RetrieveColumn(sesid, columnlist.tableid, columnlist.columnidDefault); var grbitValue = (uint)Api.RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidgrbit); return(new ColumnInfo( name, new JET_COLUMNID { Value = columnidValue }, (JET_coltyp)coltypValue, (JET_CP)codepageValue, unchecked ((int)maxLength), defaultValue, (ColumndefGrbit)grbitValue)); }
/// <summary> /// Given data retrieved from ESENT, decode the data and set the value in the ColumnValue object. /// </summary> /// <param name="value">An array of bytes.</param> /// <param name="startIndex">The starting position within the bytes.</param> /// <param name="count">The number of bytes to decode.</param> /// <param name="err">The error returned from ESENT.</param> protected override void GetValueFromBytes(byte[] value, int startIndex, int count, int err) { if (JET_wrn.ColumnNull == (JET_wrn)err) { this.Value = null; } else { this.Value = StringCache.GetString(value, startIndex, count); } }
/// <summary> /// Gets the entry the cursor is currently positioned on. /// </summary> /// <returns>The entry the cursor is currently positioned on.</returns> protected override string GetCurrent() { string name = Api.RetrieveColumnAsString( this.Sesid, this.TableidToEnumerate, this.objectlist.columnidobjectname, NativeMethods.Encoding, RetrieveColumnGrbit.None); return(StringCache.TryToIntern(name)); }
/// <summary> /// Initializes a new instance of the <see cref="JET_COLUMNBASE"/> class. /// </summary> /// <param name="value"> /// The value. /// </param> internal JET_COLUMNBASE(NATIVE_COLUMNBASE value) { this.coltyp = (JET_coltyp)value.coltyp; this.cp = (JET_CP)value.cp; this.cbMax = checked ((int)value.cbMax); this.grbit = (ColumndefGrbit)value.grbit; this.columnid = new JET_COLUMNID { Value = value.columnid }; this.szBaseTableName = StringCache.TryToIntern(value.szBaseTableName); this.szBaseColumnName = StringCache.TryToIntern(value.szBaseColumnName); }
/// <summary> /// Gets the entry the cursor is currently positioned on. /// </summary> /// <returns>The entry the cursor is currently positioned on.</returns> protected override string GetCurrent() { // 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( this.Sesid, this.TableidToEnumerate, this.objectlist.columnidobjectname, encodingOfTextColumns, RetrieveColumnGrbit.None); return(StringCache.TryToIntern(name)); }
/// <summary> /// Create an IndexInfo object from the data in the current JET_INDEXLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="indexlist">The indexlist to take the data from.</param> /// <returns>An IndexInfo object containing the information from that record.</returns> 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)); }
/// <summary> /// Creates a dictionary which maps column names to their column IDs. /// </summary> /// <param name="sesid">The sesid to use.</param> /// <param name="tableid">The table to retrieve the information for.</param> /// <returns>A dictionary mapping column names to column IDs.</returns> public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid) { JET_COLUMNLIST columnlist; JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist); // As of Sep 2015, JetGetColumnInfoW is only called for Win8+. Even though Unicode should have // worked in Win7, it wasn't reliable until Win8. Encoding encodingOfTextColumns = EsentVersion.SupportsWindows8Features ? Encoding.Unicode : LibraryHelpers.EncodingASCII; try { // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well var dict = new Dictionary <string, JET_COLUMNID>( columnlist.cRecord, StringComparer.OrdinalIgnoreCase); if (columnlist.cRecord > 0) { if (Api.TryMoveFirst(sesid, columnlist.tableid)) { do { string name = RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, encodingOfTextColumns, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var columnid = new JET_COLUMNID { Value = columnidValue }; dict.Add(name, columnid); }while (TryMoveNext(sesid, columnlist.tableid)); } } return(dict); } finally { // Close the temporary table used to return the results JetCloseTable(sesid, columnlist.tableid); } }
/// <summary> /// Creates a dictionary which maps column names to their column IDs. /// </summary> /// <param name="sesid">The sesid to use.</param> /// <param name="tableid">The table to retrieve the information for.</param> /// <returns>A dictionary mapping column names to column IDs.</returns> public static IDictionary <string, JET_COLUMNID> GetColumnDictionary(JET_SESID sesid, JET_TABLEID tableid) { JET_COLUMNLIST columnlist; JetGetTableColumnInfo(sesid, tableid, string.Empty, out columnlist); try { // esent treats column names as case-insensitive, so we want the dictionary to be case insensitive as well var dict = new Dictionary <string, JET_COLUMNID>( columnlist.cRecord, StringComparer.OrdinalIgnoreCase); if (columnlist.cRecord > 0) { if (Api.TryMoveFirst(sesid, columnlist.tableid)) { do { string name = RetrieveColumnAsString( sesid, columnlist.tableid, columnlist.columnidcolumnname, NativeMethods.Encoding, RetrieveColumnGrbit.None); name = StringCache.TryToIntern(name); var columnidValue = (uint)RetrieveColumnAsUInt32(sesid, columnlist.tableid, columnlist.columnidcolumnid); var columnid = new JET_COLUMNID { Value = columnidValue }; dict.Add(name, columnid); }while (TryMoveNext(sesid, columnlist.tableid)); } } return(dict); } finally { // Close the temporary table used to return the results JetCloseTable(sesid, columnlist.tableid); } }
/// <summary> /// Create an array of IndexSegment objects from the data in the current JET_INDEXLIST entry. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="indexlist">The indexlist to take the data from.</param> /// <returns>An array of IndexSegment objects containing the information for the current index.</returns> 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); }