Beispiel #1
0
        // retrieve the key column with JET_bitRetrieveFromPrimaryBookmark
        private void RetrieveFromPrimaryBookmark()
        {
            Console.WriteLine("\tRetrieveFromPrimaryBookmark");
            JET_TABLEID tableid;

            Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid);
            Api.JetBeginTransaction2(this.sesid, BeginTransactionGrbit.ReadOnly);

            int expectedRecordID = 7;

            this.SeekRecord(this.sesid, tableid, expectedRecordID);
            JET_COLUMNID columnid =
                (from column in this.columnInfos
                 where column.Name == "recordID"
                 select column.Columnid).Single();

            byte[] columndata = Api.RetrieveColumn(
                this.sesid, tableid, columnid, RetrieveColumnGrbit.RetrieveFromPrimaryBookmark, null);
            int actualRecordID = BitConverter.ToInt32(columndata, 0);

            BasicClass.Assert(
                expectedRecordID == actualRecordID,
                string.Format("RetrieveFromPrimaryBookmark: got {0}, expected {1}", actualRecordID, expectedRecordID));

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(this.sesid, tableid);
        }
Beispiel #2
0
        // verifies that the data in the record matches the expected values
        private void CheckColumns(JET_SESID sesid, JET_TABLEID tableid, byte[][] expectedData)
        {
            byte[][] actualData;

            actualData = this.GetColumnsWithJetRetrieveColumn(sesid, tableid);
            this.CompareColumns(actualData, expectedData);
            actualData = this.GetColumnsWithJetRetrieveColumns(sesid, tableid);
            this.CompareColumns(actualData, expectedData);

            int totalsize = 0;

            foreach (var columndata in actualData)
            {
                if (columndata != null)
                {
                    totalsize += columndata.Length;
                }
            }

            // BUGBUG: need to investigate why this gives a value which is larger than the sum of the column sizes
            var recsize = new JET_RECSIZE();

            VistaApi.JetGetRecordSize(sesid, tableid, ref recsize, GetRecordSizeGrbit.None);
            BasicClass.Assert(
                recsize.cbData + recsize.cbLongValueData >= totalsize,
                string.Format("JetGetRecordSize returned {0} bytes, expected {1}", recsize.cbData + recsize.cbLongValueData, totalsize));
        }
Beispiel #3
0
        // verifies the set of records created by Run()
        public void VerifyRecords()
        {
            Console.WriteLine("\tVerifying records");

            Api.JetBeginTransaction2(this.sesid, BeginTransactionGrbit.ReadOnly);

            JET_TABLEID tableid;

            Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid);
            Api.JetSetTableSequential(this.sesid, tableid, SetTableSequentialGrbit.None);

            Api.JetMove(this.sesid, tableid, JET_Move.First, MoveGrbit.None);
            for (int recordID = 1; recordID <= NumRecords; ++recordID)
            {
                byte[][] data = this.GenerateColumnData(recordID, recordID + 100);
                this.CheckColumns(this.sesid, tableid, data);
                try
                {
                    Api.JetMove(this.sesid, tableid, JET_Move.Next, MoveGrbit.None);
                    data = this.GetColumnsWithJetRetrieveColumn(this.sesid, tableid);
                    BasicClass.Assert(
                        NumRecords != recordID, "The last move should generate an EsentNoCurrentRecordException");
                }
                catch (EsentNoCurrentRecordException)
                {
                    BasicClass.Assert(
                        NumRecords == recordID,
                        "Only the last move should generate an EsentNoCurrentRecordException");
                }
            }

            Api.JetCloseTable(this.sesid, tableid);
            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.WaitLastLevel0Commit);
        }
Beispiel #4
0
        /// <summary>
        /// Seek for a key and make sure we don't find a record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to seek on.</param>
        /// <param name="key">The key to seek for.</param>
        /// <param name="seekOption">The seek option.</param>
        private static void VerifySeekFails(JET_SESID sesid, JET_TABLEID tableid, int key, SeekGrbit seekOption)
        {
            Console.WriteLine("\t\tSeek for {0} with {1}, expecting failure", key, seekOption);
            Api.MakeKey(sesid, tableid, key, MakeKeyGrbit.NewKey);
            bool result = Api.TrySeek(sesid, tableid, seekOption);

            BasicClass.Assert(!result, "Found the record. Expected not found.");
        }
Beispiel #5
0
        // create a temp table and insert some records
        private void CreateTempTable()
        {
            Console.WriteLine("\tTemporary Table");

            Api.JetBeginTransaction(this.sesid);

            var ci = new CultureInfo("en-us");

            var tt = new JET_OPENTEMPORARYTABLE();

            tt.prgcolumndef           = new JET_COLUMNDEF[2];
            tt.ccolumn                = 2;
            tt.pidxunicode            = new JET_UNICODEINDEX();
            tt.pidxunicode.lcid       = ci.LCID;
            tt.pidxunicode.dwMapFlags = Conversions.LCMapFlagsFromCompareOptions(CompareOptions.IgnoreCase);
            tt.grbit = TempTableGrbit.Indexed;

            tt.prgcolumndef[0] = new JET_COLUMNDEF {
                coltyp = JET_coltyp.Long, grbit = ColumndefGrbit.TTKey
            };
            tt.prgcolumndef[1] = new JET_COLUMNDEF
            {
                coltyp = JET_coltyp.LongText,
                cp     = JET_CP.Unicode,
                grbit  = ColumndefGrbit.TTKey
            };

            tt.prgcolumnid = new JET_COLUMNID[tt.prgcolumndef.Length];

            VistaApi.JetOpenTemporaryTable(this.sesid, tt);
            JET_TABLEID tableid = tt.tableid;

            for (int i = 0; i <= 5; ++i)
            {
                int    key = 5 - i;
                string s   = string.Format("Record {0}", i);

                Api.JetPrepareUpdate(this.sesid, tableid, JET_prep.Insert);
                Api.SetColumn(this.sesid, tableid, tt.prgcolumnid[0], key);
                Api.SetColumn(this.sesid, tableid, tt.prgcolumnid[1], s, Encoding.Unicode);
                Api.JetUpdate(this.sesid, tableid);
            }

            int expectedKey = 0;

            Api.MoveBeforeFirst(this.sesid, tableid);
            while (Api.TryMoveNext(this.sesid, tableid))
            {
                int actualKey = Api.RetrieveColumnAsInt32(this.sesid, tableid, tt.prgcolumnid[0]).Value;
                BasicClass.Assert(
                    expectedKey == actualKey,
                    string.Format("Temp table isn't sorted correctly (expected = {0}, actual = {1})", expectedKey, actualKey));
                expectedKey++;
            }

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(this.sesid, tableid);
        }
Beispiel #6
0
        /// <summary>
        /// Seek for a key and make sure we land on the expected record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to seek on.</param>
        /// <param name="key">The key to seek for.</param>
        /// <param name="seekOption">The seek option.</param>
        /// <param name="columnid">The columnid of the data to retrieve.</param>
        /// <param name="expected">The expected data.</param>
        private static void VerifySeekFindRecord(
            JET_SESID sesid, JET_TABLEID tableid, int key, SeekGrbit seekOption, JET_COLUMNID columnid, int expected)
        {
            Console.WriteLine("\t\tSeek for {0} with {1}, expecting {2}", key, seekOption, expected);
            Api.MakeKey(sesid, tableid, key, MakeKeyGrbit.NewKey);

            Api.JetSeek(sesid, tableid, seekOption);
            int actual = Api.RetrieveColumnAsInt32(sesid, tableid, columnid).Value;

            BasicClass.Assert(expected == actual, String.Format("Expected {0}, got {1}. Seek is broken", expected, actual));
        }
Beispiel #7
0
        // replaces records [1..numRecords] with seed = recordID+100
        private void Replace()
        {
            Console.WriteLine("\tReplace");
            JET_TABLEID tableid;

            Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid);

            Api.JetBeginTransaction(this.sesid);
            for (int i = NumRecords; i > 0; --i)
            {
                byte[][] data = this.GenerateColumnData(i, 100 + i);

                this.SeekRecord(this.sesid, tableid, i);
                byte[][] originaldata = this.GetColumnsWithJetRetrieveColumn(this.sesid, tableid);
                Api.JetPrepareUpdate(this.sesid, tableid, JET_prep.Replace);
                this.SetColumns(this.sesid, tableid, data);

                // the copy buffer should contain the new data
                byte[][] actualdata = this.GetColumnsWithJetRetrieveColumn(
                    this.sesid, tableid, RetrieveColumnGrbit.RetrieveCopy);
                this.CompareColumns(data, actualdata);

                // we haven't called update yet so this should be the original data
                actualdata = this.GetColumnsWithJetRetrieveColumn(this.sesid, tableid);
                this.CompareColumns(originaldata, actualdata);

                Api.JetUpdate(this.sesid, tableid);
            }

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);

            Api.JetBeginTransaction2(this.sesid, BeginTransactionGrbit.ReadOnly);
            Api.JetMove(this.sesid, tableid, JET_Move.Last, MoveGrbit.None);
            for (int i = NumRecords; i > 0; --i)
            {
                byte[][] data = this.GenerateColumnData(i, 100 + i);

                this.CheckColumns(this.sesid, tableid, data);
                try
                {
                    Api.JetMove(this.sesid, tableid, JET_Move.Previous, MoveGrbit.None);
                    BasicClass.Assert(1 != i, "The last move should generate an EsentNoCurrentRecordException");
                }
                catch (EsentNoCurrentRecordException)
                {
                    BasicClass.Assert(1 == i, "Only the last move should generate an EsentNoCurrentRecordException");
                }
            }

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(this.sesid, tableid);
        }
Beispiel #8
0
        private void SeekSecondaryIndex(JET_SESID sesid, JET_TABLEID tableid)
        {
            byte[][] data     = this.GetColumnsWithJetRetrieveColumn(sesid, tableid);
            byte[]   bookmark = Api.GetBookmark(sesid, tableid);
            for (int i = 0; i < this.columnInfos.Length; ++i)
            {
                string index = string.Format("index_{0}", this.columnInfos[i].Name);

                Api.JetSetCurrentIndex(sesid, tableid, index);
                string actualindex;
                Api.JetGetCurrentIndex(sesid, tableid, out actualindex, SystemParameters.NameMost);
                BasicClass.Assert(
                    string.Equals(actualindex, index, StringComparison.InvariantCultureIgnoreCase),
                    string.Format("Set index to {0}, JetGetCurrentIndex returns {1}", index, actualindex));

                // create an index range that will contain the record we want
                Api.MakeKey(sesid, tableid, data[i], MakeKeyGrbit.NewKey);
                Api.JetSeek(sesid, tableid, SeekGrbit.SeekEQ);

                Api.MakeKey(sesid, tableid, data[i], MakeKeyGrbit.StrLimit | MakeKeyGrbit.NewKey);
                Api.JetSetIndexRange(sesid, tableid, SetIndexRangeGrbit.RangeUpperLimit);

                // now move through the range until we find the record we want
                bool foundrecord = false;
                do
                {
                    // verify we have the same column value. don't retrieve the entire column as we
                    // have to deal with key truncation
                    byte[] columndata = Api.RetrieveColumn(
                        sesid, tableid, this.columnInfos[i].Columnid, RetrieveColumnGrbit.RetrieveFromIndex, null);
                    BasicClass.Assert(
                        this.CompareByteArray(columndata, data[i], null == columndata ? 0 : columndata.Length),
                        "Unexpected column value. Did we go past the end of the index range?");

                    if (this.CompareByteArray(bookmark, Api.GetBookmark(sesid, tableid), bookmark.Length))
                    {
                        BasicClass.Assert(!foundrecord, "Found the record twice");
                        foundrecord = true;
                    }
                }while (Api.TryMoveNext(sesid, tableid));
                BasicClass.Assert(foundrecord, "Didn't find the record in the secondary index");
            }
        }
Beispiel #9
0
        // insert numRecords records with recordID = [1..numRecords] and seed = recordID
        private void Insert()
        {
            Console.WriteLine("\tInsert");
            JET_TABLEID tableid;

            Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid);

            // note that the recordIDs are 1-10 NOT 0-9
            Api.JetBeginTransaction(this.sesid);
            for (int recordID = 1; recordID <= NumRecords; ++recordID)
            {
                byte[][] data = this.GenerateColumnData(recordID, recordID);

                Api.JetPrepareUpdate(this.sesid, tableid, JET_prep.Insert);
                this.SetColumns(this.sesid, tableid, data);
                Api.JetUpdate(this.sesid, tableid);
            }

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);

            Api.JetBeginTransaction2(this.sesid, BeginTransactionGrbit.ReadOnly);
            Api.JetMove(this.sesid, tableid, JET_Move.First, MoveGrbit.None);
            for (int i = 1; i <= NumRecords; ++i)
            {
                byte[][] data = this.GenerateColumnData(i, i);
                this.CheckColumns(this.sesid, tableid, data);
                try
                {
                    Api.JetMove(this.sesid, tableid, JET_Move.Next, MoveGrbit.None);
                    BasicClass.Assert(NumRecords != i, "The last move should generate an EsentNoCurrentRecordException");
                }
                catch (EsentNoCurrentRecordException)
                {
                    BasicClass.Assert(
                        NumRecords == i, "Only the last move should generate an EsentNoCurrentRecordException");
                }
            }

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(this.sesid, tableid);
        }
Beispiel #10
0
        private void JetCreateTable()
        {
            const string TableName = "tabletodelete";

            Console.WriteLine("\tJetCreateTable()");
            Api.JetBeginTransaction(this.sesid);

            JET_TABLEID tableid;

            BasicClass.Assert(
                !Api.TryOpenTable(this.sesid, this.dbid, TableName, OpenTableGrbit.None, out tableid),
                "Able to open non-existent table");
            Api.JetCreateTable(this.sesid, this.dbid, TableName, 1, 100, out tableid);
            var columndef = new JET_COLUMNDEF();

            // Add a column and an index
            columndef.coltyp = JET_coltyp.LongBinary;
            JET_COLUMNID columnid;

            Api.JetAddColumn(this.sesid, tableid, "column", columndef, null, 0, out columnid);
            Api.JetCreateIndex(this.sesid, tableid, "primary", CreateIndexGrbit.IndexPrimary, "+column\0\0", 9, 100);
            Api.JetCreateIndex(this.sesid, tableid, "secondary", CreateIndexGrbit.None, "-column\0\0", 9, 100);

            // Insert a record to force creation of the LV tree
            Api.JetPrepareUpdate(this.sesid, tableid, JET_prep.Insert);
            Api.JetSetColumn(
                this.sesid, tableid, columndef.columnid, new byte[2000], 2000, SetColumnGrbit.IntrinsicLV, null);
            Api.JetUpdate(this.sesid, tableid);

            Api.JetCloseTable(this.sesid, tableid);

            BasicClass.Assert(
                Api.TryOpenTable(this.sesid, this.dbid, TableName, OpenTableGrbit.None, out tableid),
                "Unable to open table");
            Api.JetCloseTable(this.sesid, tableid);

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
        }
Beispiel #11
0
        /// <summary>
        /// Run the test.
        /// </summary>
        public void Run()
        {
            JET_SESID sesid;

            Api.JetBeginSession(this.instance, out sesid, null, null);

            Console.WriteLine("Temporary table tests");

            Api.JetBeginTransaction(sesid);

            var ci = new CultureInfo("en-us");
            var tt = new JET_OPENTEMPORARYTABLE
            {
                prgcolumndef =
                    (from coltyp in this.coltyps select new JET_COLUMNDEF {
                    coltyp = coltyp, cp = JET_CP.Unicode
                }).
                    ToArray(),
                pidxunicode = new JET_UNICODEINDEX
                {
                    lcid       = ci.LCID,
                    dwMapFlags = Conversions.LCMapFlagsFromCompareOptions(CompareOptions.IgnoreCase)
                },
                grbit = TempTableGrbit.Indexed,
            };

            tt.ccolumn               = tt.prgcolumndef.Length;
            tt.prgcolumnid           = new JET_COLUMNID[tt.prgcolumndef.Length];
            tt.prgcolumndef[0].grbit = ColumndefGrbit.TTKey;
            tt.prgcolumndef[1].grbit = ColumndefGrbit.TTKey | ColumndefGrbit.TTDescending;
            tt.prgcolumndef[2].grbit = ColumndefGrbit.TTKey;
            tt.prgcolumndef[3].grbit = ColumndefGrbit.TTKey | ColumndefGrbit.TTDescending;

            VistaApi.JetOpenTemporaryTable(sesid, tt);

            int numrecords = 500;

            var       rand      = new Random();
            Stopwatch stopwatch = Stopwatch.StartNew();

            foreach (int i in Randomize(Enumerable.Range(0, numrecords)))
            {
                using (var update = new Update(sesid, tt.tableid, JET_prep.Insert))
                {
                    for (int j = 0; j < tt.prgcolumndef.Length; ++j)
                    {
                        Api.SetColumn(
                            sesid,
                            tt.tableid,
                            tt.prgcolumnid[j],
                            DataGenerator.GetRandomColumnData(tt.prgcolumndef[j].coltyp, tt.prgcolumndef[j].cp, rand));
                    }

                    // overwrite the first column, which is an integer key. this will be used to validate
                    // the sorting of the objects
                    Api.SetColumn(sesid, tt.tableid, tt.prgcolumnid[0], BitConverter.GetBytes(i));
                    update.Save();
                }
            }

            stopwatch.Stop();
            Console.WriteLine("\tInserted {0} records in {1}", numrecords, stopwatch.Elapsed);

            // iterate over the table to force materialization
            stopwatch = Stopwatch.StartNew();
            BasicClass.Assert(
                Enumerable.Range(0, numrecords).SequenceEqual(GetColumns(sesid, tt.tableid, tt.prgcolumnid[0])),
                "Didn't get expected keys");
            stopwatch.Stop();
            Console.WriteLine("\tRetrieved {0} records in {1}", numrecords, stopwatch.Elapsed);

            numrecords = 10000;
            stopwatch  = Stopwatch.StartNew();
            IEnumerable <int> sortedData = Enumerable.Range(0, numrecords);

            BasicClass.Assert(
                sortedData.SequenceEqual(SortWithTempTable(sesid, Randomize(sortedData))),
                "Data isn't sorted");
            stopwatch.Stop();
            Console.WriteLine("\tSorted {0} numbers in {1}", numrecords, stopwatch.Elapsed);

            Console.WriteLine("\tSeeking");
            SeekWithTempTable(sesid);

            Api.JetCommitTransaction(sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(sesid, tt.tableid);
            Api.JetEndSession(sesid, EndSessionGrbit.None);
        }
Beispiel #12
0
        // insert a record and update its long-values
        private void UpdateLongValues()
        {
            Console.WriteLine("\tUpdate Long-Values");
            JET_TABLEID tableid;

            Api.JetOpenTable(this.sesid, this.dbid, this.table, null, 0, OpenTableGrbit.None, out tableid);

            int recordID = NumRecords + 17;
            var rand     = new Random(recordID);

            var data = new byte[this.columnInfos.Length][];

            Api.JetBeginTransaction(this.sesid);

            // insert the record
            using (var update = new Update(this.sesid, tableid, JET_prep.Insert))
            {
                for (int i = 0; i < this.columnInfos.Length; ++i)
                {
                    data[i] = null;
                    if (string.Equals(
                            this.columnInfos[i].Name, "recordID", StringComparison.InvariantCultureIgnoreCase))
                    {
                        // this is the primary index column, set it to the recordID
                        data[i] = BitConverter.GetBytes(recordID);
                    }
                    else if (this.columnInfos[i].Coltyp == JET_coltyp.LongBinary ||
                             this.columnInfos[i].Coltyp == JET_coltyp.LongText)
                    {
                        data[i] = DataGenerator.GetRandomColumnData(
                            this.columnInfos[i].Coltyp, this.columnInfos[i].Cp, rand);
                    }

                    if (null != data[i])
                    {
                        Api.SetColumn(this.sesid, tableid, this.columnInfos[i].Columnid, data[i]);
                    }
                }

                update.SaveAndGotoBookmark();
            }

            this.CheckColumns(this.sesid, tableid, data);

            // update the record
            using (var update = new Update(this.sesid, tableid, JET_prep.Replace))
            {
                for (int i = 0; i < this.columnInfos.Length; ++i)
                {
                    if (this.columnInfos[i].Coltyp == JET_coltyp.LongBinary ||
                        this.columnInfos[i].Coltyp == JET_coltyp.LongText)
                    {
                        int size = Api.RetrieveColumnSize(this.sesid, tableid, this.columnInfos[i].Columnid).Value;
                        BasicClass.Assert(size == data[i].Length, "Invalid column size");

                        var setinfo = new JET_SETINFO();
                        setinfo.ibLongValue  = size / 2;
                        setinfo.itagSequence = 1;

                        // the data that will be added to the column
                        byte[] newdata = DataGenerator.GetRandomColumnData(
                            this.columnInfos[i].Coltyp, this.columnInfos[i].Cp, rand);

                        // what the final data should be
                        byte[] finaldata = null;

                        switch (rand.Next(2))
                        {
                        case 0:     // append
                            Api.SetColumn(
                                this.sesid, tableid, this.columnInfos[i].Columnid, newdata, SetColumnGrbit.AppendLV);
                            finaldata = new byte[size + newdata.Length];
                            Array.Copy(data[i], finaldata, size);
                            Array.Copy(newdata, 0, finaldata, size, newdata.Length);
                            break;

                        case 1:     // overwrite and set size
                            Api.JetSetColumn(
                                this.sesid,
                                tableid,
                                this.columnInfos[i].Columnid,
                                newdata,
                                newdata.Length,
                                SetColumnGrbit.SizeLV | SetColumnGrbit.OverwriteLV,
                                setinfo);
                            finaldata = new byte[setinfo.ibLongValue + newdata.Length];
                            Array.Copy(data[i], finaldata, setinfo.ibLongValue);
                            Array.Copy(newdata, 0, finaldata, setinfo.ibLongValue, newdata.Length);
                            break;
                        }

                        data[i] = finaldata;
                    }
                }

                update.SaveAndGotoBookmark();
            }

            this.CheckColumns(this.sesid, tableid, data);

            Api.JetCommitTransaction(this.sesid, CommitTransactionGrbit.LazyFlush);
            Api.JetCloseTable(this.sesid, tableid);
        }