/// <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++;
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
 public ColumnInformation(JET_coltyp coltyp, int colId, int maxLength, String name)
 {
     this.coltyp    = coltyp;
     this.colId     = colId;
     this.maxLength = maxLength;
     this.name      = name;
 }
Beispiel #4
0
 /// <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;
 }
Beispiel #5
0
 /// <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);
        }
Beispiel #8
0
        /// <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];
            }
        }
Beispiel #9
0
 /// <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();
     }
 }
Beispiel #10
0
        /// <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);
        }
Beispiel #11
0
 /// <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;
 }
Beispiel #12
0
 /// <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;
 }
Beispiel #13
0
 /// <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;
 }
Beispiel #14
0
 /// <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>
        /// 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));
        }
Beispiel #16
0
        /// <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);
            }
        }
Beispiel #17
0
        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[]));
            }
        }
Beispiel #18
0
        /// <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++;
            }
        }
Beispiel #19
0
        /// <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);
        }
Beispiel #20
0
        /// <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");
            }
        }
        /// <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));
        }
        // 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
        }
Beispiel #23
0
        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);
        }
Beispiel #24
0
        /// <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");
            }
        }
Beispiel #25
0
        /// <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);
 }
Beispiel #28
0
        /// <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;
            }
        }
Beispiel #29
0
        /// <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);
        }
Beispiel #30
0
        /// <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");
            }
        }
Beispiel #31
0
        /// <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");
            }
        }
Beispiel #32
0
        /// <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");
                }
            }
        }