Example #1
0
        /// <summary>
        /// Returns a key containing one ordinary key segment per given value
        /// and one wildcard key segment.
        /// </summary>
        /// <param name="values">the values for each key column that will be used to compose the key</param>
        /// <returns>A key containing one ordinary key segment per given value
        /// and one wildcard key segment.</returns>
        /// <seealso cref="Compose"/>
        /// <seealso cref="ComposePrefix"/>
        public static Key ComposeWildcard(params object[] values)
        {
            Key key = new Key();
            foreach (object value in values)
            {
                key.Add(value);
            }

            key.AddWildcard();
            return key;
        }
Example #2
0
        /// <summary>
        /// Returns a key containing one ordinary key segment per given value
        /// except that the last given value becomes a prefix key segment.
        /// </summary>
        /// <param name="values">the values for each key column that will be used to compose the key</param>
        /// <returns>A key containing one ordinary key segment per given value
        /// except that the last given value becomes a prefix key segment.</returns>
        /// <seealso cref="Compose"/>
        /// <seealso cref="ComposeWildcard"/>
        public static Key ComposePrefix(params object[] values)
        {
            Key key = new Key();
            for (int i = 0; i < values.Length - 1; i++)
            {
                key.Add(values[i]);
            }

            key.AddPrefix(values[values.Length - 1]);
            return key;
        }
Example #3
0
        /// <summary>
        /// Position the cursor at the specified key on the current index
        /// </summary>
        /// <param name="key">The full key for the desired record on the current index of the cursor</param>
        /// <remarks>
        /// Only fully qualified keys are allowed.  Partial keys and wildcards
        /// are forbidden.
        /// </remarks>
        /// <returns>true if a record was found, false otherwise</returns>
        public bool GotoKey(Key key)
        {
            lock (this.isamSession)
            {
                this.CheckDisposed();

                // if this is a Sort then seek is illegal
                //
                // NOTE:  this is a hack to work around problems in ESE/ESENT
                // that we cannot fix because we must work downlevel
                if (this.isSort)
                {
                    throw new EsentIllegalOperationException();
                }

                this.OnNavigation();

                // we only allow fully qualified keys here
                if (key.HasPrefix)
                {
                    throw new ArgumentException("Keys containing prefixes are forbidden", "key");
                }

                if (key.HasWildcard)
                {
                    throw new ArgumentException("Keys containing wildcards are forbidden", "key");
                }

                // compute the key for our seek
                Api.MakeKey(this.isamSession.Sesid, this.tableid, this.MakeKey(key, false), MakeKeyGrbit.NormalizedKey);

                // seek for the record that exactly matches this key and remember
                // if we found it
                bool found = Api.TrySeek(this.isamSession.Sesid, this.tableid, SeekGrbit.SeekEQ);

                // clear our field cache because the current record has changed
                this.fields = null;

                // if we found a record outside the index range then it doesn't count
                found = this.CheckRange() && found;

                return found;
            }
        }
Example #4
0
        /// <summary>
        /// Restricts the records that are visible to the cursor to a range of
        /// the current index delineated by the specified keys.
        /// </summary>
        /// <param name="keyStart">The partial or full key used to set the start of the records to find on the current index</param>
        /// <param name="criteriaStart">Indicates if the starting key is inclusive or exclusive</param>
        /// <param name="keyEnd">The partial or full key used to set the end of the records to find on the current index</param>
        /// <param name="criteriaEnd">Indicates if the ending key is inclusive or exclusive</param>
        /// <remarks>
        /// The restriction will remain in effect until explicitly reset or
        /// until implicitly reset by other methods as noted.
        /// <para>
        /// Any previously defined restriction will be cleared.
        /// </para>
        /// <para>
        /// The cursor will be positioned before the first record in the new
        /// restriction.
        /// </para>
        /// </remarks>
        public void FindRecordsBetween(Key keyStart, BoundCriteria criteriaStart, Key keyEnd, BoundCriteria criteriaEnd)
        {
            lock (this.isamSession)
            {
                this.CheckDisposed();
                this.OnNavigation();

                // clear our index range
                this.FindAllRecords();

                // setup the effective index range to be bounded by the specified keys
                this.keyStart = this.MakeKey(keyStart, false);
                this.grbitSeekStart = criteriaStart == BoundCriteria.Inclusive ? SeekGrbit.SeekGE : SeekGrbit.SeekGT;
                this.grbitRangeStart = criteriaStart == BoundCriteria.Inclusive
                                      ? SetIndexRangeGrbit.RangeInclusive
                                      : SetIndexRangeGrbit.None;
                this.keyEnd = this.MakeKey(keyEnd, true);
                this.grbitSeekEnd = criteriaEnd == BoundCriteria.Inclusive ? SeekGrbit.SeekLE : SeekGrbit.SeekLT;
                this.grbitRangeEnd = (criteriaEnd == BoundCriteria.Inclusive
                                     ? SetIndexRangeGrbit.RangeInclusive
                                     : SetIndexRangeGrbit.None) | SetIndexRangeGrbit.RangeUpperLimit;

                // move before first on the new index range
                this.MoveBeforeFirst();
            }
        }
Example #5
0
        /// <summary>
        /// Restricts the records that are visible to the cursor to those that
        /// match the given key by the given criteria.  The key may contain
        /// prefix or wildcard key segments which can be used to further
        /// qualify the desired matching records.
        /// </summary>
        /// <param name="criteria">The inequality used to specify which records to find on the current index</param>
        /// <param name="key">The partial or full key used to specify which records to find on the current index</param>
        /// <remarks>
        /// The restriction will remain in effect until explicitly reset or
        /// until implicitly reset by other methods as noted.
        /// <para>
        /// Any previously defined restriction will be cleared.
        /// </para>
        /// <para>
        /// The cursor will be positioned before the first record in the new
        /// restriction.
        /// </para>
        /// </remarks>
        public void FindRecords(MatchCriteria criteria, Key key)
        {
            switch (criteria)
            {
                case MatchCriteria.LessThan:
                this.FindRecordsBetween(Key.Start, BoundCriteria.Inclusive, key, BoundCriteria.Exclusive);
                    break;

                case MatchCriteria.LessThanOrEqualTo:
                    this.FindRecordsBetween(Key.Start, BoundCriteria.Inclusive, key, BoundCriteria.Inclusive);
                    break;

                case MatchCriteria.EqualTo:
                    this.FindRecordsBetween(key, BoundCriteria.Inclusive, key, BoundCriteria.Inclusive);
                    break;

                case MatchCriteria.GreaterThanOrEqualTo:
                    this.FindRecordsBetween(key, BoundCriteria.Inclusive, Key.End, BoundCriteria.Inclusive);
                    break;

                case MatchCriteria.GreaterThan:
                    this.FindRecordsBetween(key, BoundCriteria.Exclusive, Key.End, BoundCriteria.Inclusive);
                    break;
            }
        }
Example #6
0
        /// <summary>
        /// Makes the key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="end">if set to <c>true</c> specifies that the key represents the End Limit
        /// (<see cref="MakeKeyGrbit.PartialColumnStartLimit"/>/<see cref="MakeKeyGrbit.PartialColumnEndLimit"/>/
        /// <see cref="MakeKeyGrbit.FullColumnStartLimit"/>/<see cref="MakeKeyGrbit.FullColumnEndLimit"/>).</param>
        /// <returns>The byte value of the key for the index entry
        /// at the current position of a cursor.</returns>
        /// <exception cref="System.ArgumentException">the provided key must have a key segment per key column on the current index or it must contain a prefix or wildcard;key</exception>
        private byte[] MakeKey(Key key, bool end)
        {
            lock (this.isamSession)
            {
                bool firstSegment = true;
                int i = 0;
                foreach (KeySegment segment in key)
                {
                    if (i < this.CurrentIndexDefinition.KeyColumns.Count)
                    {
                        KeyColumn keyColumn = this.CurrentIndexDefinition.KeyColumns[i];

                        byte[] value = null;
                        if (!(segment.Value == null || segment.Value is DBNull))
                        {
                            Columnid isamColumnid = keyColumn.Columnid;
                            value = Converter.BytesFromObject(isamColumnid.Coltyp, false, segment.Value);
                        }

                        MakeKeyGrbit grbit = MakeKeyGrbit.None;
                        if (firstSegment == true)
                        {
                            grbit = grbit | MakeKeyGrbit.NewKey;
                        }

                        if (value != null && value.Length == 0)
                        {
                            grbit = grbit | MakeKeyGrbit.KeyDataZeroLength;
                        }

                        if (segment.Prefix == true)
                        {
                            if (end == false)
                            {
                                grbit = grbit | MakeKeyGrbit.PartialColumnStartLimit;
                            }
                            else
                            {
                                grbit = grbit | MakeKeyGrbit.PartialColumnEndLimit;
                            }
                        }
                        else if (segment.WildcardIsNext() == true)
                        {
                            if (end == false)
                            {
                                grbit = grbit | MakeKeyGrbit.FullColumnStartLimit;
                            }
                            else
                            {
                                grbit = grbit | MakeKeyGrbit.FullColumnEndLimit;
                            }
                        }

                        if (segment.Wildcard == false)
                        {
                            int valueLength = value == null ? 0 : value.Length;
                            Api.JetMakeKey(this.isamSession.Sesid, this.tableid, value, valueLength, grbit);
                            firstSegment = false;
                        }
                    }

                    i++;
                }

                if (i < this.CurrentIndexDefinition.KeyColumns.Count && key.HasPrefix == false && key.HasWildcard == false)
                {
                    throw new ArgumentException(
                        "the provided key must have a key segment per key column on the current index or it must contain a prefix or wildcard",
                        "key");
                }

                if (firstSegment)
                {
                    return null;
                }

                return Api.RetrieveKey(this.isamSession.Sesid, this.tableid, RetrieveKeyGrbit.RetrieveCopy);
            }
        }