//-----------------------------------------------------------------------
//
// 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;
}
}
}