// ---------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------
//
//
// ---------------------------------------------------------------------
namespace Microsoft.Database.Isam
{
using Microsoft.Isam.Esent.Interop;
///
/// A Table Definition contains the schema for a single table. It can be
/// used to explore the schema for an existing table, modify the schema
/// for an existing table, and to create the definition for a new table.
///
public partial class TableDefinition
{
///
/// The database
///
private IsamDatabase database = null;
///
/// The name
///
private string name = null;
///
/// The table type
///
private TableType tableType = TableType.None;
///
/// The column collection
///
private ColumnCollection columnCollection = null;
///
/// The index collection
///
private IndexCollection indexCollection = null;
///
/// Initializes a new instance of the class.
/// For use when defining a new table.
///
/// the name of the table to be defined
public TableDefinition(string name)
{
this.name = name;
this.tableType = TableType.Base;
this.columnCollection = new ColumnCollection();
this.indexCollection = new IndexCollection();
}
///
/// Initializes a new instance of the class.
/// For use when defining a new table.
///
/// the name of the table to be defined
/// Type of the table.
public TableDefinition(string name, TableType tableType)
{
this.name = name;
this.tableType = tableType;
this.columnCollection = new ColumnCollection();
this.indexCollection = new IndexCollection();
}
///
/// Initializes a new instance of the class.
///
internal TableDefinition()
{
}
///
/// Gets the name of the table.
///
///
/// The name.
///
public string Name
{
get
{
return this.name;
}
}
///
/// Gets the type of the table.
///
public TableType Type
{
get
{
return this.tableType;
}
}
///
/// Gets a collection containing the table's columns.
///
public ColumnCollection Columns
{
get
{
return this.columnCollection;
}
}
///
/// Gets a collection containing the tables indices.
///
public IndexCollection Indices
{
get
{
return this.indexCollection;
}
}
///
/// Gets the session.
///
///
/// The session.
///
internal IsamSession IsamSession
{
get
{
return this.database.IsamSession;
}
}
///
/// Gets the database.
///
///
/// The database.
///
internal IsamDatabase Database
{
get
{
return this.database;
}
}
///
/// Creates a single column with the specified definition in the table
/// underlying this table definition
///
/// The column definition.
/// The object corresponding to the
/// newly-added column.
///
/// It is currently not possible to add an AutoIncrement column to a
/// table that is being used by a Cursor. All such Cursors must be
/// disposed before the column can be successfully added.
///
public Columnid AddColumn(ColumnDefinition columnDefinition)
{
lock (this.database.IsamSession)
{
using (IsamTransaction trx = new IsamTransaction(this.database.IsamSession))
{
OpenTableGrbit grbit = OpenTableGrbit.None;
// if we are trying to add an auto-inc column then we must
// be able to open the table for exclusive access. if we can't
// then we will not be able to add the column
if ((columnDefinition.Flags & ColumnFlags.AutoIncrement) != 0)
{
grbit = grbit | OpenTableGrbit.DenyRead;
}
// open the table with the appropriate access
JET_TABLEID tableid;
Api.JetOpenTable(this.database.IsamSession.Sesid, this.database.Dbid, this.name, null, 0, grbit, out tableid);
// add the new column to the table
JET_COLUMNDEF columndef = new JET_COLUMNDEF();
columndef.coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition);
columndef.cp = JET_CP.Unicode;
columndef.cbMax = columnDefinition.MaxLength;
columndef.grbit = Converter.ColumndefGrbitFromColumnFlags(columnDefinition.Flags);
byte[] defaultValueBytes = Converter.BytesFromObject(
columndef.coltyp,
false /* ASCII */,
columnDefinition.DefaultValue);
int defaultValueBytesLength = (defaultValueBytes == null) ? 0 : defaultValueBytes.Length;
JET_COLUMNID jetColumnid;
Api.JetAddColumn(
this.database.IsamSession.Sesid,
tableid,
columnDefinition.Name,
columndef,
defaultValueBytes,
defaultValueBytesLength,
out jetColumnid);
// commit our change
Api.JetCloseTable(this.database.IsamSession.Sesid, tableid);
trx.Commit();
DatabaseCommon.SchemaUpdateID++;
// return the columnid for the new column
return new Columnid(
columnDefinition.Name,
jetColumnid,
columndef.coltyp,
columndef.cp == JET_CP.ASCII);
}
}
}
///
/// Deletes a single column from the table underlying this table
/// definition
///
/// Name of the column.
///
/// It is not possible to delete a column that is currently referenced
/// by an index over this table.
///
public void DropColumn(string columnName)
{
lock (this.database.IsamSession)
{
using (IsamTransaction trx = new IsamTransaction(this.database.IsamSession))
{
// open the table
JET_TABLEID tableid;
Api.JetOpenTable(
this.database.IsamSession.Sesid,
this.database.Dbid,
this.name,
null,
0,
OpenTableGrbit.None,
out tableid);
// delete the column from the table
Api.JetDeleteColumn(this.database.IsamSession.Sesid, tableid, columnName);
// commit our change
Api.JetCloseTable(this.database.IsamSession.Sesid, tableid);
trx.Commit();
DatabaseCommon.SchemaUpdateID++;
}
}
}
///
/// Creates a single index with the specified definition in the table
/// underlying this table definition
///
/// The index definition.
public void CreateIndex(IndexDefinition indexDefinition)
{
lock (this.database.IsamSession)
{
using (IsamTransaction trx = new IsamTransaction(this.database.IsamSession))
{
// open the table
JET_TABLEID tableid;
Api.JetOpenTable(
this.database.IsamSession.Sesid,
this.database.Dbid,
this.name,
null,
0,
OpenTableGrbit.None,
out tableid);
// add the new index to the table
JET_INDEXCREATE[] indexcreates = new JET_INDEXCREATE[1] { new JET_INDEXCREATE() };
indexcreates[0].szIndexName = indexDefinition.Name;
indexcreates[0].szKey = DatabaseCommon.IndexKeyFromIndexDefinition(indexDefinition);
indexcreates[0].cbKey = indexcreates[0].szKey.Length;
indexcreates[0].grbit = DatabaseCommon.GrbitFromIndexDefinition(indexDefinition);
indexcreates[0].ulDensity = indexDefinition.Density;
indexcreates[0].pidxUnicode = new JET_UNICODEINDEX();
indexcreates[0].pidxUnicode.lcid = indexDefinition.CultureInfo.LCID;
indexcreates[0].pidxUnicode.dwMapFlags = Converter.MapFlagsFromUnicodeIndexFlags(Converter.UnicodeFlagsFromCompareOptions(indexDefinition.CompareOptions));
indexcreates[0].rgconditionalcolumn = DatabaseCommon.ConditionalColumnsFromIndexDefinition(indexDefinition);
indexcreates[0].cConditionalColumn = indexcreates[0].rgconditionalcolumn.Length;
indexcreates[0].cbKeyMost = indexDefinition.MaxKeyLength;
Api.JetCreateIndex2(this.database.IsamSession.Sesid, tableid, indexcreates, indexcreates.Length);
// commit our change
Api.JetCloseTable(this.database.IsamSession.Sesid, tableid);
trx.Commit();
DatabaseCommon.SchemaUpdateID++;
}
}
}
///
/// Deletes a single index from the table underlying this table
///
/// The name.
///
/// It is currently not possible to delete an index that is being used
/// by a Cursor as its CurrentIndex. All such Cursors must either be
/// disposed or set to a different index before the index can be
/// successfully deleted.
///
public void DropIndex(string name)
{
lock (this.database.IsamSession)
{
using (IsamTransaction trx = new IsamTransaction(this.database.IsamSession))
{
// open the table
JET_TABLEID tableid;
Api.JetOpenTable(
this.database.IsamSession.Sesid,
this.database.Dbid,
this.name,
null,
0,
OpenTableGrbit.None,
out tableid);
// delete the index from the table
Api.JetDeleteIndex(this.database.IsamSession.Sesid, tableid, name);
// commit our change
Api.JetCloseTable(this.database.IsamSession.Sesid, tableid);
trx.Commit();
DatabaseCommon.SchemaUpdateID++;
}
}
}
///
/// Loads the specified table specified in the object.
///
/// The database.
/// The object list.
/// A corresponding to the table specified in .
internal static TableDefinition Load(IsamDatabase database, JET_OBJECTLIST objectList)
{
lock (database.IsamSession)
{
// save the database
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.database = database;
// load info for the table
tableDefinition.name = Api.RetrieveColumnAsString(
database.IsamSession.Sesid,
objectList.tableid,
objectList.columnidobjectname);
// create our column and index collections
tableDefinition.columnCollection = new ColumnCollection(database, tableDefinition.name);
tableDefinition.indexCollection = new IndexCollection(database, tableDefinition.name);
return tableDefinition;
}
}
///
/// Loads the specified table specified in the object.
///
/// The database.
/// Name of the table.
/// The object information.
/// A corresponding to the table specified in .
internal static TableDefinition Load(IsamDatabase database, string tableName, JET_OBJECTINFO objectInfo)
{
lock (database.IsamSession)
{
// save the database
TableDefinition tableDefinition = new TableDefinition();
tableDefinition.database = database;
// load info for the table
tableDefinition.name = tableName;
// create our column and index collections
tableDefinition.columnCollection = new ColumnCollection(database, tableDefinition.name);
tableDefinition.indexCollection = new IndexCollection(database, tableDefinition.name);
return tableDefinition;
}
}
}
}