//----------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. // //----------------------------------------------------------------------- namespace Microsoft.Isam.Esent.Interop { using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using Microsoft.Isam.Esent.Interop.Implementation; /// /// Helper methods for the ESENT API. These methods deal with database /// meta-data. /// public static partial class Api { #region Simpler API. Overloads that omit unused/obsolete parameters. /// /// Initialize a new ESENT session. /// /// The initialized instance to create the session in. /// Returns the created session. public static void BeginSession(JET_INSTANCE instance, out JET_SESID sesid) { Api.JetBeginSession(instance, out sesid, null, null); } /// /// Creates and attaches a database file. /// /// The session to use. /// The path to the database file to create. /// Returns the dbid of the new database. /// Database creation options. public static void CreateDatabase(JET_SESID sesid, string database, out JET_DBID dbid, CreateDatabaseGrbit grbit) { Api.JetCreateDatabase(sesid, database, null, out dbid, grbit); } /// /// Opens a database previously attached with , /// for use with a database session. This function can be called multiple times /// for the same database. /// /// The session that is opening the database. /// The database to open. /// Returns the dbid of the attached database. /// Open database options. /// An ESENT warning code. public static JET_wrn OpenDatabase( JET_SESID sesid, string database, out JET_DBID dbid, OpenDatabaseGrbit grbit) { return Api.JetOpenDatabase(sesid, database, null, out dbid, grbit); } /// /// Opens a cursor on a previously created table. /// /// The database session to use. /// The database to open the table in. /// The name of the table to open. /// Table open options. /// Returns the opened table. /// An ESENT warning. public static JET_wrn OpenTable( JET_SESID sesid, JET_DBID dbid, string tablename, OpenTableGrbit grbit, out JET_TABLEID tableid) { return Api.JetOpenTable(sesid, dbid, tablename, null, 0, grbit, out tableid); } #endregion /// /// Try to open a table. /// /// The session to use. /// The database to look for the table in. /// The name of the table. /// Table open options. /// Returns the opened tableid. /// True if the table was opened, false if the table doesn't exist. public static bool TryOpenTable( JET_SESID sesid, JET_DBID dbid, string tablename, OpenTableGrbit grbit, out JET_TABLEID tableid) { var err = (JET_err)Impl.JetOpenTable(sesid, dbid, tablename, null, 0, grbit, out tableid); if (JET_err.ObjectNotFound == err) { return false; } Api.Check((int)err); Debug.Assert(err >= JET_err.Success, "Exception should have been thrown in case of error"); return true; } /// /// Creates a dictionary which maps column names to their column IDs. /// /// The sesid to use. /// The table to retrieve the information for. /// A dictionary mapping column names to column IDs. public static IDictionary 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( 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); } } /// /// Get the columnid of the specified column. /// /// The session to use. /// The table containing the column. /// The name of the column. /// The id of the column. public static JET_COLUMNID GetTableColumnid(JET_SESID sesid, JET_TABLEID tableid, string columnName) { JET_COLUMNDEF columndef; JetGetTableColumnInfo(sesid, tableid, columnName, out columndef); return columndef.columnid; } /// /// Iterates over all the columns in the table, returning information about each one. /// /// The session to use. /// The table to retrieve column information for. /// An iterator over ColumnInfo for each column in the table. public static IEnumerable GetTableColumns(JET_SESID sesid, JET_TABLEID tableid) { return new GenericEnumerable(() => new TableidColumnInfoEnumerator(sesid, tableid)); } /// /// Iterates over all the columns in the table, returning information about each one. /// /// The session to use. /// The database containing the table. /// The name of the table. /// An iterator over ColumnInfo for each column in the table. public static IEnumerable GetTableColumns(JET_SESID sesid, JET_DBID dbid, string tablename) { if (null == tablename) { throw new ArgumentNullException("tablename"); } return new GenericEnumerable(() => new TableColumnInfoEnumerator(sesid, dbid, tablename)); } /// /// Iterates over all the indexes in the table, returning information about each one. /// /// The session to use. /// The table to retrieve index information for. /// An iterator over an IndexInfo for each index in the table. public static IEnumerable GetTableIndexes(JET_SESID sesid, JET_TABLEID tableid) { return new GenericEnumerable(() => new TableidIndexInfoEnumerator(sesid, tableid)); } /// /// Iterates over all the indexs in the table, returning information about each one. /// /// The session to use. /// The database containing the table. /// The name of the table. /// An iterator over an IndexInfo for each index in the table. public static IEnumerable GetTableIndexes(JET_SESID sesid, JET_DBID dbid, string tablename) { if (null == tablename) { throw new ArgumentNullException("tablename"); } return new GenericEnumerable(() => new TableIndexInfoEnumerator(sesid, dbid, tablename)); } /// /// Returns the names of the tables in the database. /// /// The session to use. /// The database containing the table. /// An iterator over the names of the tables in the database. public static IEnumerable GetTableNames(JET_SESID sesid, JET_DBID dbid) { return new GenericEnumerable(() => new TableNameEnumerator(sesid, dbid)); } /// /// Retrieves information about indexes on a table. /// /// The session to use. /// The table to retrieve index information about. /// The name of the index. /// Filled in with information about indexes on the table. /// The type of information to retrieve. /// true if there was no error, false if the index wasn't found. Throws for other Jet errors. public static bool TryJetGetTableIndexInfo( JET_SESID sesid, JET_TABLEID tableid, string indexname, out JET_INDEXID result, JET_IdxInfo infoLevel) { int err = Impl.JetGetTableIndexInfo(sesid, tableid, indexname, out result, infoLevel); if ((JET_err)err == JET_err.IndexNotFound) { return false; } Api.Check(err); return true; } /// /// Determines the name of the current index of a given cursor. /// /// /// This name is also used to later re-select that index as the current index using /// . It can also be used to discover the properties of that index using /// JetGetTableIndexInfo. /// /// The returned name of the index will be null if the current index is the clustered index and no primary /// index was explicitly defined. /// /// The session to use. /// The cursor to get the index name for. /// Returns the name of the index. public static string JetGetCurrentIndex(JET_SESID sesid, JET_TABLEID tableid) { string indexName; Api.JetGetCurrentIndex(sesid, tableid, out indexName, SystemParameters.NameMost); return string.IsNullOrEmpty(indexName) ? null : indexName; } } }