/// <summary> /// Fetches the Column Definition for the specified columnid. /// </summary> /// <value> /// The <see cref="ColumnDefinition"/> for the specifed column identifier /// </value> /// <param name="columnid">The columnid.</param> /// <returns>The <see cref="ColumnDefinition"/> for the specified column identifier.</returns> public ColumnDefinition this[Columnid columnid] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedColumnDefinition != columnid.Name.ToLower(CultureInfo.InvariantCulture) || this.columnUpdateID != DatabaseCommon.SchemaUpdateID) { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); this.columnDefinition = ColumnDefinition.Load(this.database, this.tableName, columnBase); this.cachedColumnDefinition = columnid.Name.ToLower(CultureInfo.InvariantCulture); this.columnUpdateID = DatabaseCommon.SchemaUpdateID; } return(this.columnDefinition); } } else { return((ColumnDefinition)this.Dictionary[columnid.Name.ToLower(CultureInfo.InvariantCulture)]); } } }
/// <summary> /// Initializes a new instance of the <see cref="KeyColumn"/> class. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="isAscending">if set to <c>true</c> [is ascending].</param> internal KeyColumn(Columnid columnid, bool isAscending) { this.columnid = columnid; this.name = columnid.Name; this.isAscending = isAscending; this.readOnly = true; }
/// <summary> /// Determines if the table contains a column with the given columnid /// </summary> /// <param name="columnid">The columnid.</param> /// <returns>Whether the specified column exists in the collection.</returns> public bool Contains(Columnid columnid) { if (this.database != null) { lock (this.database.IsamSession) { bool exists = false; try { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); exists = true; } catch (EsentColumnNotFoundException) { } return(exists); } } else { return(Dictionary.Contains(columnid.Name.ToLower(CultureInfo.InvariantCulture))); } }
/// <summary> /// Accessor for any itag of a column, converted to/from an object /// </summary> /// <value> /// The <see cref="System.Object"/>. /// </value> /// <param name="columnid">The columnid.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> /// <remarks> /// The index argument is 0-based, we add 1 to get the itag /// </remarks> public object this[Columnid columnid, int index] { get { return(this.RetrieveColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index)); } set { this.SetColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index, value); } }
/// <summary> /// The field values for the specified column /// </summary> /// <value> /// The <see cref="FieldValueCollection"/>. /// </value> /// <param name="column">the column ID whose field values are desired</param> /// <returns>A <see cref="FieldValueCollection"/> object to access values of this column.</returns> public FieldValueCollection this[Columnid column] { get { return((FieldValueCollection)Dictionary[column.Name.ToLower(CultureInfo.InvariantCulture)]); } set { this.Dictionary[column.Name.ToLower(CultureInfo.InvariantCulture)] = value; } }
/// <summary> /// Retrieves the column. /// </summary> /// <param name="columnDefinition">The column definition.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> private object RetrieveColumn(ColumnDefinition columnDefinition, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); using (IsamTransaction trx = new IsamTransaction(this.isamSession, true)) { Columnid columnid = columnDefinition.Columnid; return(this.RetrieveColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index)); } } }
/// <summary> /// Sets the column. /// </summary> /// <param name="columnDefinition">The column definition.</param> /// <param name="index">The index.</param> /// <param name="obj">The object.</param> private void SetColumn(ColumnDefinition columnDefinition, int index, object obj) { lock (this.isamSession) { this.cursor.CheckDisposed(); using (IsamTransaction trx = new IsamTransaction(this.isamSession, true)) { Columnid columnid = columnDefinition.Columnid; this.SetColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index, obj); trx.Commit(); } } }
/// <summary> /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnList"/>. /// </summary> /// <param name="database">The database.</param> /// <param name="tableName">Name of the table.</param> /// <param name="columnList">The <see cref="JET_COLUMNLIST"/> object that represents the row in /// the temptable for this particular column.</param> /// <returns> /// A <see cref="ColumnDefinition"/> object based on the current row in the temptable /// represented by <paramref name="columnList"/>. /// </returns> internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNLIST columnList) { lock (database.IsamSession) { using (IsamTransaction trx = new IsamTransaction(database.IsamSession)) { // load info for the column ColumnDefinition columnDefinition = new ColumnDefinition(); JET_SESID sesid = database.IsamSession.Sesid; // 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 columnName = Api.RetrieveColumnAsString( database.IsamSession.Sesid, columnList.tableid, columnList.columnidcolumnname, encodingOfTextColumns); JET_COLUMNBASE columnbase; Api.JetGetColumnInfo(database.IsamSession.Sesid, database.Dbid, tableName, columnName, out columnbase); columnDefinition.columnid = new Columnid(columnbase); columnDefinition.name = columnDefinition.columnid.Name; columnDefinition.type = columnDefinition.columnid.Type; ColumndefGrbit grbitColumn = (ColumndefGrbit)Api.RetrieveColumnAsUInt32(sesid, columnList.tableid, columnList.columnidgrbit).GetValueOrDefault(); columnDefinition.flags = ColumnFlagsFromGrbits(grbitColumn); columnDefinition.maxLength = Api.RetrieveColumnAsInt32(sesid, columnList.tableid, columnList.columnidcbMax).GetValueOrDefault(); columnDefinition.IsAscii = columnbase.cp == JET_CP.ASCII; byte[] defaultValueBytes = Api.RetrieveColumn(sesid, columnList.tableid, columnList.columnidDefault); Columnid isamColumnid = columnDefinition.columnid; columnDefinition.defaultValue = Converter.ObjectFromBytes( isamColumnid.Coltyp, columnDefinition.IsAscii, defaultValueBytes); columnDefinition.ReadOnly = true; return(columnDefinition); } } }
/// <summary> /// Calculates the size of the specified multivalue stored in the specified column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="index">The index.</param> /// <returns>Returns the size of the specified multivalue stored in the specified column.</returns> public long SizeOf(Columnid columnid, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); } int itagSequence = index + 1; int?size = Api.RetrieveColumnSize( this.isamSession.Sesid, this.tableid, columnid.InteropColumnid, itagSequence, RetrieveColumnGrbit.None); return(size.GetValueOrDefault()); } }
/// <summary> /// Initializes a new instance of the <see cref="ColumnDefinition"/> class. /// </summary> /// <param name="columnid">The columnid.</param> internal ColumnDefinition(Columnid columnid) { this.columnid = columnid; this.name = columnid.Name; this.type = columnid.Type; }
/// <summary> /// Returns whether the specifed column exists in the row. /// </summary> /// <param name="column">The column.</param> /// <returns>Whether the specifed column exists in the row.</returns> public bool Contains(Columnid column) { return(this.Dictionary.Contains(column.Name.ToLower(CultureInfo.InvariantCulture))); }
/// <summary> /// Initializes a new instance of the <see cref="KeyColumn"/> class. /// For use when defining a new key column in an /// index. /// </summary> /// <param name="name"> /// The name of the column in the table to be used for this key column. /// </param> /// <param name="isAscending"> /// True if the sort order of this key column is ascending, false if descending. /// </param> public KeyColumn(string name, bool isAscending) { this.columnid = null; this.name = name; this.isAscending = isAscending; }
/// <summary> /// Removes the specified columnid. /// </summary> /// <param name="columnid">The columnid.</param> public void Remove(Columnid columnid) { Dictionary.Remove(columnid.Name.ToLower(CultureInfo.InvariantCulture)); }
/// <summary> /// Accessor for any itag of a column, converted to/from an object /// </summary> /// <value> /// The <see cref="System.Object"/>. /// </value> /// <param name="columnid">The columnid.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> /// <remarks> /// The index argument is 0-based, we add 1 to get the itag /// </remarks> public object this[Columnid columnid, int index] { get { return this.RetrieveColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index); } set { this.SetColumn(columnid.InteropColumnid, columnid.Coltyp, columnid.IsAscii, index, value); } }
/// <summary> /// Calculates the size of the specified multivalue stored in the specified column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="index">The index.</param> /// <returns>Returns the size of the specified multivalue stored in the specified column.</returns> public long SizeOf(Columnid columnid, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); } int itagSequence = index + 1; int? size = Api.RetrieveColumnSize( this.isamSession.Sesid, this.tableid, columnid.InteropColumnid, itagSequence, RetrieveColumnGrbit.None); return size.GetValueOrDefault(); } }
/// <summary> /// Calculates the size of the specified column. /// </summary> /// <param name="columnid">The columnid.</param> /// <returns>Returns the size of the specified column.</returns> public long SizeOf(Columnid columnid) { return this.SizeOf(columnid, 0); }
/// <summary> /// Initializes a new instance of the <see cref="ConditionalColumn"/> class. /// For use when defining a new conditional /// column in an index. /// </summary> /// <param name="name"> /// The name of the column in the table to be used for this conditional column. /// </param> /// <param name="mustBeNull"> /// True if the column must be null for the record to be visible in the index, /// false if the column must be non-null for the record to be visible in the index. /// </param> public ConditionalColumn(string name, bool mustBeNull) { this.columnid = null; this.name = name; this.mustBeNull = mustBeNull; }
/// <summary> /// Fetches the Column Definition for the specified columnid. /// </summary> /// <value> /// The <see cref="ColumnDefinition"/> for the specifed column identifier /// </value> /// <param name="columnid">The columnid.</param> /// <returns>The <see cref="ColumnDefinition"/> for the specified column identifier.</returns> public ColumnDefinition this[Columnid columnid] { get { if (this.database != null) { lock (this.database.IsamSession) { if (this.cachedColumnDefinition != columnid.Name.ToLower(CultureInfo.InvariantCulture) || this.columnUpdateID != DatabaseCommon.SchemaUpdateID) { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); this.columnDefinition = ColumnDefinition.Load(this.database, this.tableName, columnBase); this.cachedColumnDefinition = columnid.Name.ToLower(CultureInfo.InvariantCulture); this.columnUpdateID = DatabaseCommon.SchemaUpdateID; } return this.columnDefinition; } } else { return (ColumnDefinition)this.Dictionary[columnid.Name.ToLower(CultureInfo.InvariantCulture)]; } } }
/// <summary> /// Creates a <see cref="TableDefinition"/> object from a <see cref="JET_OPENTEMPORARYTABLE"/> /// object, suitable for caching. /// </summary> /// <param name="tableDefinition">The table definition.</param> /// <param name="openTemporaryTable">The open temporary table.</param> /// <returns>A <see cref="TableDefinition"/> object suitable for caching.</returns> private static TableDefinition MakeTableDefinitionToCache( TableDefinition tableDefinition, JET_OPENTEMPORARYTABLE openTemporaryTable) { // set the new table properties TableDefinition tableDefinitionToCache = new TableDefinition(tableDefinition.Name, tableDefinition.Type); // add the columns complete with the columnids generated when the // TT was created // // NOTE: this processing loop has to mirror the loop used to generate // the columndefs in MakeOpenTemporaryTable int currentColumndef = 0; foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { ColumnDefinition columnDefinition = tableDefinition.Columns[keyColumn.Name]; Columnid columnid = new Columnid( columnDefinition.Name, openTemporaryTable.prgcolumnid[currentColumndef], DatabaseCommon.ColtypFromColumnDefinition(columnDefinition), columnDefinition.IsAscii); ColumnDefinition columnDefinitionToCache = new ColumnDefinition(columnid); columnDefinitionToCache.Flags = columnDefinition.Flags; columnDefinitionToCache.MaxLength = columnDefinition.MaxLength; columnDefinitionToCache.ReadOnly = true; tableDefinitionToCache.Columns.Add(columnDefinitionToCache); currentColumndef++; } } // next collect the rest of the columns and put them after the key // columns, skipping over the columns we already added foreach (ColumnDefinition columnDefinition in tableDefinition.Columns) { bool alreadyAdded = false; foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { if (keyColumn.Name.ToLower(CultureInfo.InvariantCulture) == columnDefinition.Name.ToLower(CultureInfo.InvariantCulture)) { alreadyAdded = true; } } } if (!alreadyAdded) { Columnid columnid = new Columnid( columnDefinition.Name, openTemporaryTable.prgcolumnid[currentColumndef], DatabaseCommon.ColtypFromColumnDefinition(columnDefinition), columnDefinition.IsAscii); ColumnDefinition columnDefinitionToCache = new ColumnDefinition(columnid); columnDefinitionToCache.Flags = columnDefinition.Flags; columnDefinitionToCache.MaxLength = columnDefinition.MaxLength; columnDefinitionToCache.ReadOnly = true; tableDefinitionToCache.Columns.Add(columnDefinitionToCache); currentColumndef++; } } tableDefinitionToCache.Columns.ReadOnly = true; // add the indices foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { IndexDefinition indexDefinitionToCache = new IndexDefinition(indexDefinition.Name); indexDefinitionToCache.Flags = indexDefinition.Flags; indexDefinitionToCache.Density = 100; indexDefinitionToCache.CultureInfo = indexDefinition.CultureInfo; indexDefinitionToCache.CompareOptions = indexDefinition.CompareOptions; indexDefinitionToCache.MaxKeyLength = indexDefinition.MaxKeyLength; foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { Columnid columnid = tableDefinitionToCache.Columns[keyColumn.Name].Columnid; KeyColumn keyColumnToCache = new KeyColumn(columnid, keyColumn.IsAscending); indexDefinitionToCache.KeyColumns.Add(keyColumnToCache); } indexDefinitionToCache.KeyColumns.ReadOnly = true; indexDefinitionToCache.ReadOnly = true; tableDefinitionToCache.Indices.Add(indexDefinitionToCache); } tableDefinitionToCache.Indices.ReadOnly = true; // return the table definition return(tableDefinitionToCache); }
/// <summary> /// Calculates the size of the specified column. /// </summary> /// <param name="columnid">The columnid.</param> /// <returns>Returns the size of the specified column.</returns> public long SizeOf(Columnid columnid) { return(this.SizeOf(columnid, 0)); }
/// <summary> /// Gets the fields of the current row. /// </summary> /// <param name="grbit">The grbit.</param> /// <returns>A <see cref="FieldCollection"/> object to allow retrieval of all fields of the current row.</returns> internal FieldCollection GetFields(RetrieveColumnGrbit grbit) { JET_PFNREALLOC allocator = (context, pv, cb) => IntPtr.Zero == pv ? Marshal.AllocHGlobal(new IntPtr(cb)) : Marshal.ReAllocHGlobal(pv, new IntPtr(cb)); lock (this.isamSession) { this.CheckDisposed(); this.CheckRecord(); EnumerateColumnsGrbit enumerateGrbit = ((grbit & RetrieveColumnGrbit.RetrieveCopy) != 0) ? EnumerateColumnsGrbit.EnumerateCopy : EnumerateColumnsGrbit.None; using (IsamTransaction trx = new IsamTransaction(this.isamSession, true)) { // enumerate all field values in the current record or copy // buffer JET_ENUMCOLUMN[] jecs; int numColumnValues; Api.JetEnumerateColumns( this.isamSession.Sesid, this.tableid, 0, // numColumnids null, // columnids out numColumnValues, out jecs, allocator, IntPtr.Zero, // allocatorContext, int.MaxValue, enumerateGrbit); // create a field collection to contain our field values FieldCollection fields = new FieldCollection(); // save the location of the source record for these field values fields.Location = this.Location; // fill the field collection with our field values if (jecs != null && jecs.Length > 0) { foreach (JET_ENUMCOLUMN jec in jecs) { if (jec.rgEnumColumnValue != null && jec.rgEnumColumnValue.Length > 0) { JET_COLUMNBASE columnbase; VistaApi.JetGetTableColumnInfo( this.isamSession.Sesid, this.tableid, jec.columnid, out columnbase); Columnid columnid = new Columnid(columnbase); bool isAscii = columnbase.cp == JET_CP.ASCII; FieldValueCollection values = new FieldValueCollection(columnid); foreach (JET_ENUMCOLUMNVALUE jecv in jec.rgEnumColumnValue) { // FUTURE-2013/11/15-martinc: Drat, this is an IntPtr, and ObjectFromBytes() really // wants a byte[] array. Copying the data to a byte array just to simply // re-interpret it as an object is inefficient. // We should write Converter.ObjectFromIntPtr... byte[] bytesData = new byte[jecv.cbData]; Marshal.Copy(jecv.pvData, bytesData, 0, bytesData.Length); values.Add(Converter.ObjectFromBytes(columnbase.coltyp, isAscii, bytesData)); } values.ReadOnly = true; fields.Add(values); } } } fields.ReadOnly = true; // Return the field collection. return fields; } } }
/// <summary> /// Initializes a new instance of the <see cref="FieldValueCollection"/> class. /// </summary> /// <param name="columnid">The columnid.</param> internal FieldValueCollection(Columnid columnid) { this.columnid = columnid; }
/// <summary> /// Determines if the table contains a column with the given columnid /// </summary> /// <param name="columnid">The columnid.</param> /// <returns>Whether the specified column exists in the collection.</returns> public bool Contains(Columnid columnid) { if (this.database != null) { lock (this.database.IsamSession) { bool exists = false; try { JET_COLUMNBASE columnBase; Api.JetGetColumnInfo( this.database.IsamSession.Sesid, this.database.Dbid, this.tableName, columnid.Name, out columnBase); exists = true; } catch (EsentColumnNotFoundException) { } return exists; } } else { return Dictionary.Contains(columnid.Name.ToLower(CultureInfo.InvariantCulture)); } }
private static AttributeSyntax GetSyntaxFromColumnType(Columnid column) { Type colType = column.Type; if(colType == typeof(int)) { return AttributeSyntax.Int; } else if(colType == typeof(Int64)) { return AttributeSyntax.Int64; } else if (colType == typeof(byte)) { return AttributeSyntax.Bool; } else if (colType == typeof(byte[])) { return AttributeSyntax.OctetString; } else { return AttributeSyntax.Undefined; } }
/// <summary> /// Creates a <see cref="ColumnDefinition"/> object representing the column passed in by <paramref name="columnBase"/>. /// </summary> /// <param name="database">The database.</param> /// <param name="tableName">Name of the table.</param> /// <param name="columnBase">The <see cref="JET_COLUMNBASE"/> object that represents this particular column.</param> /// <returns> /// A <see cref="ColumnDefinition"/> object based on the <paramref name="columnBase"/> object. /// </returns> internal static ColumnDefinition Load(IsamDatabase database, string tableName, JET_COLUMNBASE columnBase) { lock (database.IsamSession) { using (IsamTransaction trx = new IsamTransaction(database.IsamSession)) { JET_SESID sesid = database.IsamSession.Sesid; // load info for the column ColumnDefinition columnDefinition = new ColumnDefinition(); columnDefinition.columnid = new Columnid(columnBase); columnDefinition.name = columnDefinition.columnid.Name; columnDefinition.type = columnDefinition.columnid.Type; columnDefinition.flags = ColumnFlagsFromGrbits(columnBase.grbit); columnDefinition.maxLength = (int)columnBase.cbMax; columnDefinition.IsAscii = columnBase.cp == JET_CP.ASCII; // there is currently no efficient means to retrieve the // default value of a specific column from JET. so, we are // going to reach into the catalog and fetch it directly JET_TABLEID tableidCatalog; Api.JetOpenTable( sesid, database.Dbid, "MSysObjects", null, 0, OpenTableGrbit.ReadOnly, out tableidCatalog); Api.JetSetCurrentIndex(sesid, tableidCatalog, "RootObjects"); Api.MakeKey(sesid, tableidCatalog, true, MakeKeyGrbit.NewKey); Api.MakeKey( sesid, tableidCatalog, Converter.BytesFromObject(JET_coltyp.Text, true, columnBase.szBaseTableName), MakeKeyGrbit.None); Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ); JET_COLUMNBASE columnbaseCatalog; Api.JetGetTableColumnInfo(sesid, tableidCatalog, "ObjidTable", out columnbaseCatalog); uint objidTable = Api.RetrieveColumnAsUInt32(sesid, tableidCatalog, columnbaseCatalog.columnid).GetValueOrDefault(); Api.JetSetCurrentIndex(sesid, tableidCatalog, "Name"); Api.MakeKey(sesid, tableidCatalog, objidTable, MakeKeyGrbit.NewKey); Api.MakeKey(sesid, tableidCatalog, (short)2, MakeKeyGrbit.None); Api.MakeKey(sesid, tableidCatalog, columnBase.szBaseColumnName, Encoding.ASCII, MakeKeyGrbit.None); Api.JetSeek(sesid, tableidCatalog, SeekGrbit.SeekEQ); Api.JetGetTableColumnInfo(sesid, tableidCatalog, "DefaultValue", out columnbaseCatalog); byte[] defaultValueBytes = Api.RetrieveColumn(sesid, tableidCatalog, columnbaseCatalog.columnid); Columnid isamColumnid = columnDefinition.columnid; columnDefinition.defaultValue = Converter.ObjectFromBytes( isamColumnid.Coltyp, columnDefinition.IsAscii, defaultValueBytes); columnDefinition.ReadOnly = true; return(columnDefinition); } } }
/// <summary> /// Initializes a new instance of the <see cref="ConditionalColumn"/> class. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="mustBeNull">if set to <c>true</c> [must be null].</param> internal ConditionalColumn(Columnid columnid, bool mustBeNull) { this.columnid = columnid; this.name = columnid.Name; this.mustBeNull = mustBeNull; }