/// <summary> /// Sets the column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="coltyp">The coltyp.</param> /// <param name="isAscii">Whether a textual column is Ascii.</param> /// <param name="index">The index.</param> /// <param name="obj">The object.</param> /// <exception cref="System.InvalidOperationException">You may only update fields through Cursor.EditRecord.</exception> /// <remarks> /// Itags start at 1, so we add 1 to the index /// </remarks> private void SetColumn(JET_COLUMNID columnid, JET_coltyp coltyp, bool isAscii, int index, object obj) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); throw new InvalidOperationException("You may only update fields through Cursor.EditRecord."); } // if this is a Sort or PreSortTemporary TT and we are setting // an LV column then always attempt to use intrinsic LVs SetColumnGrbit grbitSet = SetColumnGrbit.None; if ((this.cursor.TableDefinition.Type == TableType.Sort || this.cursor.TableDefinition.Type == TableType.PreSortTemporary) && (coltyp == JET_coltyp.LongText || coltyp == JET_coltyp.LongBinary)) { grbitSet = grbitSet | SetColumnGrbit.IntrinsicLV; } JET_SETINFO setinfo = new JET_SETINFO(); setinfo.ibLongValue = 0; setinfo.itagSequence = index + 1; byte[] bytes = Converter.BytesFromObject(coltyp, isAscii, obj); int bytesLength = bytes == null ? 0 : bytes.Length; Api.JetSetColumn(this.isamSession.Sesid, this.tableid, columnid, bytes, bytesLength, grbitSet, setinfo); this.updateID++; } }
public ColumnConverter() { Type underlyingType = IsNullableType(typeof(TColumn)) ? GetUnderlyingType(typeof(TColumn)) : typeof(TColumn); if (RetrieveColumnMethodNamesMap.ContainsKey(underlyingType)) { this.columnSetter = CreateSetColumnDelegate(); this.columnRetriever = CreateRetrieveColumnDelegate(); this.coltyp = ColumnTypeMap[underlyingType]; } #if ESENTCOLLECTIONS_SUPPORTS_SERIALIZATION else if (IsSerializable(typeof(TColumn))) { this.columnSetter = (s, t, c, o) => Api.SerializeObjectToColumn(s, t, c, o); this.columnRetriever = (s, t, c) => (TColumn)Api.DeserializeObjectFromColumn(s, t, c); this.coltyp = JET_coltyp.LongBinary; } #endif else { throw new ArgumentOutOfRangeException("TColumn", typeof(TColumn), "Not supported for SetColumn"); } // Compile the new delegates. RuntimeHelpers.PrepareDelegate(this.columnSetter); RuntimeHelpers.PrepareDelegate(this.columnRetriever); }
public ColumnInformation(JET_coltyp coltyp, int colId, int maxLength, String name) { this.coltyp = coltyp; this.colId = colId; this.maxLength = maxLength; this.name = name; }
/// <summary> /// Initializes a new instance of the IndexSegment class. /// </summary> /// <param name="name">The name of the indexed column.</param> /// <param name="coltyp">The type of the column.</param> /// <param name="isAscending">True if the column is ascending.</param> /// <param name="isASCII">True if the column is over an ASCII column.</param> internal IndexSegment( string name, JET_coltyp coltyp, bool isAscending, bool isASCII) { this.ColumnName = name; this.Coltyp = coltyp; this.IsAscending = isAscending; this.IsASCII = isASCII; }
/// <summary> /// Add a column to the table. /// </summary> /// <param name="sesid">The session to use.</param> /// <param name="tableid">The table to add the column to.</param> /// <param name="name">The name of the column.</param> /// <param name="coltyp">The type of the column.</param> /// <param name="cp">The codepage to use.</param> private void AddColumn(JET_SESID sesid, JET_TABLEID tableid, string name, JET_coltyp coltyp, JET_CP cp) { JET_COLUMNID ignored; Api.JetAddColumn( sesid, tableid, name, new JET_COLUMNDEF() { coltyp = coltyp, cp = cp }, null, 0, out ignored); }
// Put the column value to the ESE. void LoadVal(string strVal, JET_COLUMNID idColumn, JET_coltyp ct, JET_CP cp) { if (String.IsNullOrEmpty(strVal)) { return; } byte[] val = null; if (ct == JET_coltyp.Currency) // int64 { val = BitConverter.GetBytes(Convert.ToUInt64(strVal, 16)); } else if (ct == JET_coltyp.Long) // int32 { val = BitConverter.GetBytes(Convert.ToUInt32(strVal, 16)); } else if (ct == JET_coltyp.Short) // int16 { val = BitConverter.GetBytes(Convert.ToUInt16(strVal, 16)); } else if (ct == JET_coltyp.UnsignedByte) // uint8 { val = new byte[1] { Convert.ToByte(strVal, 16) } } ; else if (ct == JET_coltyp.DateTime) // DateTime { DateTime dt = DateTime.Parse(strVal, null, System.Globalization.DateTimeStyles.RoundtripKind); double dbl = dt.ToOADate(); val = BitConverter.GetBytes(dbl); } else if (ct == JET_coltyp.Text || ct == JET_coltyp.LongText) // Text { if (cp == JET_CP.Unicode) { val = TSV.UnescapeUnicode(strVal).ToArray(); } else { val = TSV.UnescapeASCII(strVal).ToArray(); } } else { val = Convert.FromBase64String(strVal); // Anything else } JET_SETINFO si = new JET_SETINFO(); si.itagSequence = 0; Api.JetSetColumn(sess.idSession, idTable, idColumn, val, val.Length, SetColumnGrbit.None, si); }
/// <summary> /// Initializes a new instance of the ColumnConverter class. /// </summary> /// <param name="type">The type to convert to/from.</param> public ColumnConverter(Type type) { if (null == type) { throw new ArgumentNullException("type"); } if (!SetColumnDelegates.ContainsKey(type)) { if (!IsSerializable(type)) { throw new ArgumentOutOfRangeException("type", type, "Not supported for SetColumn"); } this.setColumn = (s, t, c, o) => Api.SerializeObjectToColumn(s, t, c, o); } else { this.setColumn = SetColumnDelegates[type]; } if (!RetrieveColumnDelegates.ContainsKey(type)) { if (!IsSerializable(type)) { throw new ArgumentOutOfRangeException("type", type, "Not supported for RetrieveColumn"); } this.retrieveColumn = (s, t, c) => Api.DeserializeObjectFromColumn(s, t, c); } else { this.retrieveColumn = RetrieveColumnDelegates[type]; } if (!Coltyps.ContainsKey(type)) { if (!IsSerializable(type)) { throw new ArgumentOutOfRangeException("type", type, "Has no matching ESENT column type"); } this.coltyp = JET_coltyp.LongBinary; } else { this.coltyp = Coltyps[type]; } }
/// <summary>Throw an exception if this attribute is not compatible with the type of the field/property.</summary> /// <param name="t">The type of the field/property this attribute is applied.</param> public override void verifyTypeSupport(Type t) { if (t.Equals(typeof(int))) { m_cp = JET_coltyp.Long; } else if (t.Equals(typeof(long))) { m_cp = JET_coltyp.Currency; } else { throw new System.Runtime.Serialization.SerializationException(); } }
/// <summary> /// Initializes a new instance of the ColumnInfo class. /// </summary> /// <param name="name">Name of the column.</param> /// <param name="columnid">ID of the column.</param> /// <param name="coltyp">Type of the column.</param> /// <param name="cp">Codepage of the column.</param> /// <param name="maxLength">Maximum length of the column.</param> /// <param name="defaultValue">Column default value.</param> /// <param name="grbit">Column option.</param> internal ColumnInfo( string name, JET_COLUMNID columnid, JET_coltyp coltyp, JET_CP cp, int maxLength, byte[] defaultValue, ColumndefGrbit grbit) { this.Name = name; this.Columnid = columnid; this.Coltyp = coltyp; this.Cp = cp; this.MaxLength = maxLength; this.defaultValue = (null == defaultValue) ? null : new ReadOnlyCollection<byte>(defaultValue); this.Grbit = grbit; }
/// <summary> /// Initializes a new instance of the ColumnInfo class. /// </summary> /// <param name="name">Name of the column.</param> /// <param name="columnid">ID of the column.</param> /// <param name="coltyp">Type of the column.</param> /// <param name="cp">Codepage of the column.</param> /// <param name="maxLength">Maximum length of the column.</param> /// <param name="defaultValue">Column default value.</param> /// <param name="grbit">Column option.</param> internal ColumnInfo( string name, JET_COLUMNID columnid, JET_coltyp coltyp, JET_CP cp, int maxLength, byte[] defaultValue, ColumndefGrbit grbit) { this.Name = name; this.Columnid = columnid; this.Coltyp = coltyp; this.Cp = cp; this.MaxLength = maxLength; this.DefaultValue = defaultValue; this.Grbit = grbit; }
/// <summary> /// Initializes a new instance of the ColumnInfo class. /// </summary> /// <param name="name">Name of the column.</param> /// <param name="columnid">ID of the column.</param> /// <param name="coltyp">Type of the column.</param> /// <param name="cp">Codepage of the column.</param> /// <param name="maxLength">Maximum length of the column.</param> /// <param name="defaultValue">Column default value.</param> /// <param name="grbit">Column option.</param> internal ColumnInfo( string name, JET_COLUMNID columnid, JET_coltyp coltyp, JET_CP cp, int maxLength, byte[] defaultValue, ColumndefGrbit grbit) { this.Name = name; this.Columnid = columnid; this.Coltyp = coltyp; this.Cp = cp; this.MaxLength = maxLength; this.defaultValue = (null == defaultValue) ? null : Array.AsReadOnly(defaultValue); this.Grbit = grbit; }
/// <summary> /// Verify that CreateColumnMetaDataFromColumnInfo sets the specified ColumnType. /// </summary> /// <param name="jetColtyp">The coltyp for the ColumnInfo.</param> /// <param name="type">The expected ColumnType in the ColumnMetaData.</param> private void VerifyCreateColumnMetaDataSetsType(JET_coltyp jetColtyp, ColumnType type) { var info = new ColumnInfo( "test", this.columnid, jetColtyp, JET_CP.None, 0, null, ColumndefGrbit.None); var expected = new ColumnMetaData { Name = "test", Type = type, Columnid = this.columnid, }; AssertColumnMetaDataAreEqual(expected, this.converter.CreateColumnMetaDataFromColumnInfo(info)); }
/// <summary> /// Retrieves the column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="coltyp">The coltyp.</param> /// <param name="isAscii">Whether a textual column is Ascii.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> /// <remarks> /// Itags start at 1, so we add 1 to the index /// </remarks> private object RetrieveColumn(JET_COLUMNID columnid, JET_coltyp coltyp, bool isAscii, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); } JET_RETINFO retinfo = new JET_RETINFO(); retinfo.ibLongValue = 0; retinfo.itagSequence = index + 1; byte[] bytes = Api.RetrieveColumn(this.isamSession.Sesid, this.tableid, columnid, this.grbit, retinfo); object obj = Converter.ObjectFromBytes(coltyp, isAscii, bytes); return(obj); } }
public static Type ToClr(this JET_coltyp coltyp) { switch (coltyp) { case JET_coltyp.Bit: return(typeof(bool)); case JET_coltyp.UnsignedByte: return(typeof(byte)); case JET_coltyp.Short: return(typeof(short)); case JET_coltyp.Long: return(typeof(int)); case JET_coltyp.Currency: return(typeof(long)); case JET_coltyp.IEEESingle: return(typeof(float)); case JET_coltyp.IEEEDouble: return(typeof(double)); case JET_coltyp.DateTime: return(typeof(DateTime)); case JET_coltyp.LongText: case JET_coltyp.Text: return(typeof(string)); default: return(typeof(byte[])); } }
/// <summary> /// Makes the <see cref="JET_OPENTEMPORARYTABLE"/> object to later open it. /// </summary> /// <param name="tableDefinition">The table definition.</param> /// <returns>The newly created <see cref="JET_OPENTEMPORARYTABLE"/> object.</returns> private JET_OPENTEMPORARYTABLE MakeOpenTemporaryTable(TableDefinition tableDefinition) { JET_OPENTEMPORARYTABLE openTemporaryTable = new JET_OPENTEMPORARYTABLE(); // allocate room for our columns int currentColumndef = 0; openTemporaryTable.ccolumn = tableDefinition.Columns.Count; openTemporaryTable.prgcolumndef = new JET_COLUMNDEF[openTemporaryTable.ccolumn]; openTemporaryTable.prgcolumnid = new JET_COLUMNID[openTemporaryTable.ccolumn]; for (int coldef = 0; coldef < openTemporaryTable.ccolumn; ++coldef) { openTemporaryTable.prgcolumndef[coldef] = new JET_COLUMNDEF(); } // first, collect all the key columns in order and put them as the // first columndefs. we have to do this to guarantee that the TT // is sorted properly foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { ColumnDefinition columnDefinition = tableDefinition.Columns[keyColumn.Name]; openTemporaryTable.prgcolumndef[currentColumndef].coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); openTemporaryTable.prgcolumndef[currentColumndef].cp = JET_CP.Unicode; openTemporaryTable.prgcolumndef[currentColumndef].cbMax = columnDefinition.MaxLength; openTemporaryTable.prgcolumndef[currentColumndef].grbit = (ColumndefGrbit)columnDefinition.Flags | ColumndefGrbit.TTKey | (keyColumn.IsAscending ? ColumndefGrbit.None : ColumndefGrbit.TTDescending); 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) { openTemporaryTable.prgcolumndef[currentColumndef].coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); openTemporaryTable.prgcolumndef[currentColumndef].cp = JET_CP.Unicode; openTemporaryTable.prgcolumndef[currentColumndef].cbMax = columnDefinition.MaxLength; openTemporaryTable.prgcolumndef[currentColumndef].grbit = Converter.ColumndefGrbitFromColumnFlags(columnDefinition.Flags); currentColumndef++; } } // set the index flags foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { openTemporaryTable.pidxunicode = new JET_UNICODEINDEX(); openTemporaryTable.pidxunicode.lcid = indexDefinition.CultureInfo.LCID; UnicodeIndexFlags unicodeIndexFlags = Converter.UnicodeFlagsFromCompareOptions(indexDefinition.CompareOptions); openTemporaryTable.pidxunicode.dwMapFlags = Converter.MapFlagsFromUnicodeIndexFlags(unicodeIndexFlags); } // infer the TT mode of operation and set its grbits accordingly bool haveColumnWithLongValue = false; foreach (ColumnDefinition columnDefinition in tableDefinition.Columns) { JET_coltyp coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); if (coltyp == JET_coltyp.LongText || coltyp == JET_coltyp.LongBinary) { haveColumnWithLongValue = true; } } bool haveIndexWithSortNullsHigh = false; foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { if ((indexDefinition.Flags & IndexFlags.SortNullsHigh) != 0) { haveIndexWithSortNullsHigh = true; } } if (tableDefinition.Type == TableType.Sort) { foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { if ((indexDefinition.Flags & (IndexFlags.Unique | IndexFlags.Primary)) == 0) { // External Sort without duplicate removal openTemporaryTable.grbit = Server2003Grbits.ForwardOnly | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else { // External Sort TT with deferred duplicate removal openTemporaryTable.grbit = TempTableGrbit.Unique | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } } } else if (tableDefinition.Type == TableType.PreSortTemporary) { // Pre-sorted B+ Tree TT with deferred duplicate removal openTemporaryTable.grbit = TempTableGrbit.Indexed | TempTableGrbit.Unique | TempTableGrbit.Updatable | TempTableGrbit.Scrollable | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else if (tableDefinition.Type == TableType.Temporary) { if (tableDefinition.Indices.Count != 0) { // B+ Tree TT with immediate duplicate removal openTemporaryTable.grbit = TempTableGrbit.Indexed | TempTableGrbit.Unique | TempTableGrbit.Updatable | TempTableGrbit.Scrollable | TempTableGrbit.ForceMaterialization | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else { // B+ Tree TT with a sequential index openTemporaryTable.grbit = TempTableGrbit.Updatable | TempTableGrbit.Scrollable; } } // set the key construction parameters for the TT foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { openTemporaryTable.cbKeyMost = indexDefinition.MaxKeyLength; openTemporaryTable.cbVarSegMac = 0; } // return the constructed JET_OPENTEMPORARYTABLE (whew!) return(openTemporaryTable); }
/// <summary> /// Initializes a new instance of the <see cref="Columnid"/> class. /// </summary> /// <param name="name">The column name.</param> /// <param name="columnid">The column identifier.</param> /// <param name="coltyp">The column type.</param> /// <param name="isAscii">If it's a text column, whether the data is ASCII or Unicode.</param> internal Columnid(string name, JET_COLUMNID columnid, JET_coltyp coltyp, bool isAscii) { this.name = name; this.columnid = columnid; this.coltyp = coltyp; this.isAscii = isAscii; switch (coltyp) { case JET_coltyp.Nil: throw new ArgumentOutOfRangeException("columnid.Type", "Nil is not valid"); case JET_coltyp.Bit: this.type = typeof(bool); break; case JET_coltyp.UnsignedByte: this.type = typeof(byte); break; case JET_coltyp.Short: this.type = typeof(short); break; case JET_coltyp.Long: this.type = typeof(int); break; case JET_coltyp.Currency: this.type = typeof(long); break; case JET_coltyp.IEEESingle: this.type = typeof(float); break; case JET_coltyp.IEEEDouble: this.type = typeof(double); break; case JET_coltyp.DateTime: this.type = typeof(DateTime); break; case JET_coltyp.Binary: this.type = typeof(byte[]); break; case JET_coltyp.Text: this.type = typeof(string); break; case JET_coltyp.LongBinary: this.type = typeof(byte[]); break; case JET_coltyp.LongText: this.type = typeof(string); break; case VistaColtyp.UnsignedLong: this.type = typeof(uint); break; case VistaColtyp.LongLong: this.type = typeof(long); break; case VistaColtyp.GUID: this.type = typeof(Guid); break; case VistaColtyp.UnsignedShort: this.type = typeof(ushort); break; default: throw new ArgumentOutOfRangeException("columnid.Coltyp", "unknown type"); } }
// Retrieve the column value from the ESE. // Returns the properly-escaped string suitable for TSV file. string getStringValue(TextWriter bw, JET_COLUMNID idColumn, int itagSequence, JET_coltyp ct, JET_CP cp) { JET_RETINFO ri = new JET_RETINFO(); ri.itagSequence = itagSequence; int cbSize; Api.JetRetrieveColumn(sess.idSession, idTable, idColumn, buff, buff.Length, out cbSize, RetrieveColumnGrbit.None, ri); if (cbSize <= 0) { return(""); } if (ct == JET_coltyp.Currency) // int64 { Debug.Assert(8 == cbSize); return(BitConverter.ToUInt64(buff, 0).ToString("X16")); } if (ct == JET_coltyp.Long) // int32 { Debug.Assert(4 == cbSize); return(BitConverter.ToUInt32(buff, 0).ToString("X8")); } if (ct == JET_coltyp.Short) // int16 { Debug.Assert(2 == cbSize); return(BitConverter.ToUInt16(buff, 0).ToString("X4")); } if (ct == JET_coltyp.UnsignedByte) // uint8 { Debug.Assert(1 == cbSize); return(buff[0].ToString("X2")); } if (ct == JET_coltyp.DateTime) // DateTime { Debug.Assert(8 == cbSize); double dbl = BitConverter.ToDouble(buff, 0); DateTime dt = Conversions.ConvertDoubleToDateTime(dbl); return(dt.ToString("o")); } if (ct == JET_coltyp.Text || ct == JET_coltyp.LongText) // Text { if (cp == JET_CP.Unicode) { return(TSV.EscapeUnicode(buff, cbSize)); } else { return(TSV.EscapeASCII(buff, cbSize)); } } return(Convert.ToBase64String(buff, 0, cbSize)); // Anything else }
public static void AddColumn(JET_SESID session, JET_TABLEID tableId, string name, JET_coltyp type, JET_CP cp, ColumndefGrbit grBit) { JET_COLUMNID columnid; Api.JetAddColumn(session, tableId, name, new JET_COLUMNDEF { coltyp = type, cp = cp, grbit = grBit }, null, 0, out columnid); }
/// <summary> /// Gets random data for a column. /// </summary> /// <param name="coltyp">The type of the column.</param> /// <param name="cp"> /// The code page of the column. Only used for text columns. /// </param> /// <param name="rand">Random number generator.</param> /// <returns> /// Random data for the column. /// </returns> public static byte[] GetRandomColumnData(JET_coltyp coltyp, JET_CP cp, Random rand) { byte[] data; switch (coltyp) { case JET_coltyp.Bit: data = new byte[1]; data[0] = (0 == rand.Next(2)) ? checked((byte)0x0) : checked((byte)0xFF); break; case JET_coltyp.UnsignedByte: data = new byte[1]; rand.NextBytes(data); break; case JET_coltyp.Short: data = new byte[2]; rand.NextBytes(data); break; case JET_coltyp.Long: data = new byte[4]; rand.NextBytes(data); break; case JET_coltyp.Currency: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.IEEESingle: data = new byte[4]; rand.NextBytes(data); break; case JET_coltyp.IEEEDouble: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.DateTime: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.Binary: { int size = rand.Next(255) + 1; data = GetRandomBinaryBytes(size, rand); break; } case JET_coltyp.Text: { // GetRandomUnicodeBytes will round up the size of // an odd-sized request so a request for 255 bytes will // give a 256 byte buffer, which is too large. Restrict // unicode columns to 254 bytes. int size = (JET_CP.ASCII == cp) ? rand.Next(255) : rand.Next(254) + 1; data = (JET_CP.ASCII == cp) ? GetRandomAsciiBytes(size, rand) : GetRandomUnicodeBytes(size, rand); break; } case JET_coltyp.LongBinary: { int size = rand.Next(9 * 1024) + 1; data = GetRandomBinaryBytes(size, rand); break; } case JET_coltyp.LongText: { int size = rand.Next(9 * 1024) + 1; data = (JET_CP.ASCII == cp) ? GetRandomAsciiBytes(size, rand) : GetRandomUnicodeBytes(size, rand); break; } case VistaColtyp.UnsignedLong: data = new byte[4]; rand.NextBytes(data); break; case VistaColtyp.LongLong: data = new byte[8]; rand.NextBytes(data); break; case VistaColtyp.GUID: data = new byte[16]; rand.NextBytes(data); break; case VistaColtyp.UnsignedShort: data = new byte[2]; rand.NextBytes(data); break; default: throw new Exception("Invalid coltyp"); } return data; }
static JET_COLUMNDEF Def(JET_coltyp colType, ColumndefGrbit grbit, int cbMax) { JET_COLUMNDEF def = new JET_COLUMNDEF(); def.grbit = grbit; def.coltyp = colType; if (cbMax > 0) def.cbMax = cbMax; return def; }
static JET_COLUMNDEF Def(JET_coltyp colType, ColumndefGrbit grbit) { return Def(colType, grbit,-1); }
/// <summary> /// Retrieves the column. /// </summary> /// <param name="columnid">The columnid.</param> /// <param name="coltyp">The coltyp.</param> /// <param name="isAscii">Whether a textual column is Ascii.</param> /// <param name="index">The index.</param> /// <returns>The value stored within.</returns> /// <remarks> /// Itags start at 1, so we add 1 to the index /// </remarks> private object RetrieveColumn(JET_COLUMNID columnid, JET_coltyp coltyp, bool isAscii, int index) { lock (this.isamSession) { this.cursor.CheckDisposed(); if ((this.grbit & RetrieveColumnGrbit.RetrieveCopy) == 0) { this.cursor.CheckRecord(); } JET_RETINFO retinfo = new JET_RETINFO(); retinfo.ibLongValue = 0; retinfo.itagSequence = index + 1; byte[] bytes = Api.RetrieveColumn(this.isamSession.Sesid, this.tableid, columnid, this.grbit, retinfo); object obj = Converter.ObjectFromBytes(coltyp, isAscii, bytes); return obj; } }
/// <summary> /// Gets random data for a column. /// </summary> /// <param name="coltyp">The type of the column.</param> /// <param name="cp"> /// The code page of the column. Only used for text columns. /// </param> /// <param name="rand">Random number generator.</param> /// <returns> /// Random data for the column. /// </returns> public static byte[] GetRandomColumnData(JET_coltyp coltyp, JET_CP cp, Random rand) { byte[] data; switch (coltyp) { case JET_coltyp.Bit: data = new byte[1]; data[0] = (0 == rand.Next(2)) ? checked ((byte)0x0) : checked ((byte)0xFF); break; case JET_coltyp.UnsignedByte: data = new byte[1]; rand.NextBytes(data); break; case JET_coltyp.Short: data = new byte[2]; rand.NextBytes(data); break; case JET_coltyp.Long: data = new byte[4]; rand.NextBytes(data); break; case JET_coltyp.Currency: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.IEEESingle: data = new byte[4]; rand.NextBytes(data); break; case JET_coltyp.IEEEDouble: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.DateTime: data = new byte[8]; rand.NextBytes(data); break; case JET_coltyp.Binary: { int size = rand.Next(255) + 1; data = GetRandomBinaryBytes(size, rand); break; } case JET_coltyp.Text: { // GetRandomUnicodeBytes will round up the size of // an odd-sized request so a request for 255 bytes will // give a 256 byte buffer, which is too large. Restrict // unicode columns to 254 bytes. int size = (JET_CP.ASCII == cp) ? rand.Next(255) : rand.Next(254) + 1; data = (JET_CP.ASCII == cp) ? GetRandomAsciiBytes(size, rand) : GetRandomUnicodeBytes(size, rand); break; } case JET_coltyp.LongBinary: { int size = rand.Next(9 * 1024) + 1; data = GetRandomBinaryBytes(size, rand); break; } case JET_coltyp.LongText: { int size = rand.Next(9 * 1024) + 1; data = (JET_CP.ASCII == cp) ? GetRandomAsciiBytes(size, rand) : GetRandomUnicodeBytes(size, rand); break; } case VistaColtyp.UnsignedLong: data = new byte[4]; rand.NextBytes(data); break; case VistaColtyp.LongLong: data = new byte[8]; rand.NextBytes(data); break; case VistaColtyp.GUID: data = new byte[16]; rand.NextBytes(data); break; case VistaColtyp.UnsignedShort: data = new byte[2]; rand.NextBytes(data); break; default: throw new Exception("Invalid coltyp"); } return(data); }
/// <summary> /// Given a column type and an object, convert the object to an array of bytes /// </summary> /// <remarks> /// This method uses System.Convert and System.BitConverter to do automatic type conversion (e.g. String -> Boolean) /// </remarks> /// <param name="type">The type of the database column that this object is to be stored in</param> /// <param name="isASCII">For text columns, is the column an ASCII column. Ignored for other types</param> /// <param name="o">The object to be converted</param> /// <returns>An array of bytes representing the object</returns> /// <exception cref="InvalidCastException">This conversion is not supported</exception> /// <exception cref="ArgumentOutOfRangeException">Unknown column type</exception> public static byte[] BytesFromObject(JET_coltyp type, bool isASCII, object o) { if (o is DBNull) { return(null); } if (null == o) { return(null); } switch (type) { case JET_coltyp.Nil: throw new ArgumentOutOfRangeException("type", "Nil is not valid"); case JET_coltyp.Bit: return(BitConverter.GetBytes(Convert.ToBoolean(o))); case JET_coltyp.UnsignedByte: byte[] bytes = new byte[1]; bytes[0] = (byte)o; return(bytes); case JET_coltyp.Short: return(BitConverter.GetBytes(Convert.ToInt16(o))); case JET_coltyp.Long: return(BitConverter.GetBytes(Convert.ToInt32(o))); case VistaColtyp.LongLong: return(BitConverter.GetBytes(Convert.ToInt64(o))); case JET_coltyp.Currency: return(BitConverter.GetBytes(Convert.ToInt64(o))); case JET_coltyp.IEEESingle: return(BitConverter.GetBytes(Convert.ToSingle(o))); case JET_coltyp.IEEEDouble: return(BitConverter.GetBytes(Convert.ToDouble(o))); case VistaColtyp.UnsignedShort: return(BitConverter.GetBytes(Convert.ToUInt16(o))); case VistaColtyp.UnsignedLong: return(BitConverter.GetBytes(Convert.ToUInt32(o))); case JET_coltyp.Binary: return((byte[])o); case JET_coltyp.LongBinary: return((byte[])o); case JET_coltyp.DateTime: // Internally DateTime is stored as a double, mapping to a COLEDateTime DateTime datetime = Convert.ToDateTime(o); double oleDateTime = datetime.ToOADate(); return(BitConverter.GetBytes(oleDateTime)); case JET_coltyp.Text: if (isASCII) { return(Encoding.ASCII.GetBytes(o.ToString())); } else { return(Encoding.Unicode.GetBytes(o.ToString())); } case JET_coltyp.LongText: if (isASCII) { return(Encoding.ASCII.GetBytes(o.ToString())); } else { return(Encoding.Unicode.GetBytes(o.ToString())); } case VistaColtyp.GUID: if (o is string) { Guid guid = new Guid((string)o); return(guid.ToByteArray()); } else if (o is byte[]) { Guid guid = new Guid((byte[])o); return(guid.ToByteArray()); } else { // if o isn't a Guid, this will throw an exception return(((Guid)o).ToByteArray()); } default: throw new ArgumentOutOfRangeException("type", "unknown type"); } }
/// <summary> /// Given a column type and a Byte array, convert the bytes into a CLR object /// </summary> /// <remarks> /// This method uses System.BitConverter to do the conversion /// </remarks> /// <param name="type">The type of the database column that this bytes were retrieved from</param> /// <param name="isASCII">For text columns, is the column an ASCII column. Ignored for other types</param> /// <param name="value">The bytes to be converted</param> /// <returns>An Object constructed from the bytes or DBNull for a null value</returns> /// <exception cref="ArgumentOutOfRangeException">Unknown column type or incorrect Byte array size</exception> public static object ObjectFromBytes(JET_coltyp type, bool isASCII, byte[] value) { if (null == value) { return(DBNull.Value); } switch (type) { case JET_coltyp.Nil: throw new ArgumentOutOfRangeException("type", "Nil is not valid"); case JET_coltyp.Bit: return(BitConverter.ToBoolean(value, 0)); case JET_coltyp.UnsignedByte: return(value[0]); case JET_coltyp.Short: return(BitConverter.ToInt16(value, 0)); case JET_coltyp.Long: return(BitConverter.ToInt32(value, 0)); case VistaColtyp.LongLong: return(BitConverter.ToInt64(value, 0)); case JET_coltyp.Currency: return(BitConverter.ToInt64(value, 0)); case JET_coltyp.IEEESingle: return(BitConverter.ToSingle(value, 0)); case JET_coltyp.IEEEDouble: return(BitConverter.ToDouble(value, 0)); case VistaColtyp.UnsignedShort: return(BitConverter.ToUInt16(value, 0)); case VistaColtyp.UnsignedLong: return(BitConverter.ToUInt32(value, 0)); case JET_coltyp.Binary: return(value); case JET_coltyp.LongBinary: return(value); case JET_coltyp.Text: if (isASCII) { return(new string(Encoding.ASCII.GetChars(value))); } else { return(new string(Encoding.Unicode.GetChars(value))); } case JET_coltyp.LongText: if (isASCII) { return(new string(Encoding.ASCII.GetChars(value))); } else { return(new string(Encoding.Unicode.GetChars(value))); } case VistaColtyp.GUID: return(new Guid(value)); case JET_coltyp.DateTime: // Internally DateTime is stored as a double, mapping to a COLEDateTime return(DateTime.FromOADate(BitConverter.ToDouble(value, 0))); default: throw new ArgumentOutOfRangeException("type", "unknown type"); } }
/// <summary> /// Validates the table definition. /// </summary> /// <param name="tableDefinition">The table definition.</param> /// <exception cref="System.ArgumentException"> /// Illegal name for a temporary table.;tableDefinition /// or /// Illegal TableType for a temporary table.;tableDefinition /// or /// Temporary tables must have at least one column.;tableDefinition /// or /// Illegal name for a column in a temporary table.;tableDefinition /// or /// Illegal ColumnFlags for a column in a temporary table.;tableDefinition /// or /// Default values are not supported for temporary table columns.;tableDefinition /// or /// Temporary tables of type TableType.Sort and TableType.PreSortTemporary must have an index defined.;tableDefinition /// or /// Temporary tables may only have a single index defined.;tableDefinition /// or /// Illegal name for an index in a temporary table.;tableDefinition /// or /// Illegal IndexFlags for an index in a temporary table.;tableDefinition /// or /// Illegal or unsupported MaxKeyLength for an index in a temporary table.;tableDefinition /// or /// No KeyColumns for an index in a temporary table.;tableDefinition /// or /// Too many KeyColumns for an index in a temporary table.;tableDefinition /// or /// A KeyColumn for an index in the temporary table refers to a column that doesn't exist.;tableDefinition /// or /// Conditional columns are not supported for temporary table indices.;tableDefinition /// or /// Temporary tables of type TableType.PreSortTemporary and TableType.Temporary must have a primary index defined.;tableDefinition /// </exception> private void ValidateTableDefinition(TableDefinition tableDefinition) { // validate the table's properties DatabaseCommon.CheckName( tableDefinition.Name, new ArgumentException("Illegal name for a temporary table.", "tableDefinition")); if (tableDefinition.Name == null) { throw new ArgumentException("Illegal name for a temporary table.", "tableDefinition"); } if ( !(tableDefinition.Type == TableType.Sort || tableDefinition.Type == TableType.PreSortTemporary || tableDefinition.Type == TableType.Temporary)) { throw new ArgumentException("Illegal TableType for a temporary table.", "tableDefinition"); } // validate all columns if (tableDefinition.Columns.Count == 0) { throw new ArgumentException("Temporary tables must have at least one column.", "tableDefinition"); } foreach (ColumnDefinition columnDefinition in tableDefinition.Columns) { DatabaseCommon.CheckName( columnDefinition.Name, new ArgumentException("Illegal name for a column in a temporary table.", "tableDefinition")); if (columnDefinition.Name == null) { throw new ArgumentException("Illegal name for a column in a temporary table.", "tableDefinition"); } if (tableDefinition.Type == TableType.Sort || tableDefinition.Type == TableType.PreSortTemporary) { JET_coltyp coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); if (coltyp == JET_coltyp.LongText || coltyp == JET_coltyp.LongBinary) { // timestamp when ESE/ESENT supports JET_bitTTIntrinsicLVsOnly DatabaseCommon.CheckEngineVersion( this.IsamSession, DatabaseCommon.ESENTVersion(6, 1, 6492, 0), DatabaseCommon.ESEVersion(14, 0, 46, 0), new ArgumentException( "LongText and LongBinary columns are not supported for columns in a temporary table of type TableType.Sort or TableType.PreSortTemporary on this version of the database engine.", "tableDefinition")); } } if (0 != (columnDefinition.Flags & ~(ColumnFlags.Fixed | ColumnFlags.Variable | ColumnFlags.Sparse | ColumnFlags.NonNull | ColumnFlags.MultiValued))) { throw new ArgumentException("Illegal ColumnFlags for a column in a temporary table.", "tableDefinition"); } if (columnDefinition.DefaultValue != null) { throw new ArgumentException("Default values are not supported for temporary table columns.", "tableDefinition"); } } // validate all indices if (tableDefinition.Indices.Count == 0 && (tableDefinition.Type == TableType.Sort || tableDefinition.Type == TableType.PreSortTemporary)) { throw new ArgumentException("Temporary tables of type TableType.Sort and TableType.PreSortTemporary must have an index defined.", "tableDefinition"); } if (tableDefinition.Indices.Count > 1) { throw new ArgumentException("Temporary tables may only have a single index defined.", "tableDefinition"); } foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { DatabaseCommon.CheckName( indexDefinition.Name, new ArgumentException("Illegal name for an index in a temporary table.", "tableDefinition")); if (indexDefinition.Name == null) { throw new ArgumentException("Illegal name for an index in a temporary table.", "tableDefinition"); } if (0 != (indexDefinition.Flags & ~(IndexFlags.Unique | IndexFlags.Primary | IndexFlags.AllowNull | IndexFlags.SortNullsLow | IndexFlags.SortNullsHigh | IndexFlags.AllowTruncation))) { throw new ArgumentException("Illegal IndexFlags for an index in a temporary table.", "tableDefinition"); } // Require AllowTruncation. if (0 == (indexDefinition.Flags & IndexFlags.AllowTruncation)) { throw new ArgumentException("Illegal IndexFlags for an index in a temporary table.", "tableDefinition"); } // 255 in XP. long keyMost = this.IsamSession.IsamInstance.IsamSystemParameters.KeyMost; if (indexDefinition.MaxKeyLength < 255 || indexDefinition.MaxKeyLength > keyMost) { throw new ArgumentException("Illegal or unsupported MaxKeyLength for an index in a temporary table.", "tableDefinition"); } // 12 in XP. 16 in Vista. int keyColumnMost = 16; if (indexDefinition.KeyColumns.Count == 0) { throw new ArgumentException("No KeyColumns for an index in a temporary table.", "tableDefinition"); } if (indexDefinition.KeyColumns.Count > keyColumnMost) { throw new ArgumentException("Too many KeyColumns for an index in a temporary table.", "tableDefinition"); } foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { if (!tableDefinition.Columns.Contains(keyColumn.Name)) { throw new ArgumentException("A KeyColumn for an index in the temporary table refers to a column that doesn't exist.", "tableDefinition"); } } if (indexDefinition.ConditionalColumns.Count != 0) { throw new ArgumentException("Conditional columns are not supported for temporary table indices.", "tableDefinition"); } if ((indexDefinition.Flags & IndexFlags.Primary) == 0 && (tableDefinition.Type == TableType.PreSortTemporary || tableDefinition.Type == TableType.Temporary)) { throw new ArgumentException("Temporary tables of type TableType.PreSortTemporary and TableType.Temporary must have a primary index defined.", "tableDefinition"); } } }