コード例 #1
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");
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Creates a single table with the specified definition in the database
        /// </summary>
        /// <param name="tableDefinition">The table definition.</param>
        /// <exception cref="EsentTableDuplicateException">
        /// Thrown when the table definition overlaps with an already existing table.
        /// </exception>
        /// <exception cref="System.ArgumentException">A MaxKeyLength &gt; 255 is not supported for indices over a temporary table on this version of the database engine.;tableDefinition</exception>
        public override void CreateTable(TableDefinition tableDefinition)
        {
            lock (this.IsamSession)
            {
                this.CheckDisposed();

                // validate the table definition for creating a TT
                this.ValidateTableDefinition(tableDefinition);

                // convert the given table definition into an JET_OPENTEMPORARYTABLE
                // struct that we will use to create the TT
                JET_OPENTEMPORARYTABLE openTemporaryTable = this.MakeOpenTemporaryTable(tableDefinition);

                // check if the TT already exists
                if (this.Exists(tableDefinition.Name))
                {
                    throw new EsentTableDuplicateException();
                }

                // do not allow the TT to be created if the session is in a
                // transaction.  we disallow this to sidestep the problem where
                // JET will automatically close (and destroy) the TT if the
                // current level of the transaction is aborted
                if (this.IsamSession.TransactionLevel > 0)
                {
                    // NOTE:  i'm thinking that this requirement is pretty lame,
                    // especially since it only hits us on an abort.  I am going
                    // to allow this for now and see what happens
                    // throw new ArgumentException( "We do not currently allow you to create temp tables while inside of a transaction." );
                }

                // create the TT
                JET_TABLEID tableid = new JET_TABLEID();

                if (DatabaseCommon.CheckEngineVersion(
                        this.IsamSession,
                        DatabaseCommon.ESENTVersion(6, 0, 6000, 0),
                        DatabaseCommon.ESEVersion(8, 0, 685, 0)))
                {
                    VistaApi.JetOpenTemporaryTable(this.IsamSession.Sesid, openTemporaryTable);
                    tableid = openTemporaryTable.tableid;
                }
                else
                {
                    if (openTemporaryTable.cbKeyMost > 255)
                    {
                        throw new ArgumentException("A MaxKeyLength > 255 is not supported for indices over a temporary table on this version of the database engine.", "tableDefinition");
                    }

                    Api.JetOpenTempTable2(
                        this.IsamSession.Sesid,
                        openTemporaryTable.prgcolumndef,
                        openTemporaryTable.prgcolumndef.Length,
                        openTemporaryTable.pidxunicode.lcid,
                        openTemporaryTable.grbit,
                        out tableid,
                        openTemporaryTable.prgcolumnid);
                }

                // re-create the TT's schema to reflect the created TT
                TableDefinition tableDefinitionToCache = MakeTableDefinitionToCache(tableDefinition, openTemporaryTable);

                // cache the TT and its handle
                TempTableHandle tempTableHandle = new TempTableHandle(
                    tableDefinitionToCache.Name,
                    this.IsamSession.Sesid,
                    tableid,
                    tableDefinitionToCache.Type == TableType.Sort || tableDefinitionToCache.Type == TableType.PreSortTemporary);

                this.Tables.Add(tableDefinitionToCache);
                this.TempTableHandles.Add(tempTableHandle);
                this.IsamSession.IsamInstance.TempTableHandles.Add(tempTableHandle);
            }
        }