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