Ejemplo n.º 1
0
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.  
        /// </summary>
        /// <remarks>
        /// This is an internal method that takes a buffer offset as well as size.
        /// </remarks>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="data">The data buffer to be retrieved into.</param>
        /// <param name="dataSize">The size of the data buffer.</param>
        /// <param name="dataOffset">Offset into the data buffer to read data into.</param>
        /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>An ESENT warning code.</returns>
        public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            if (dataOffset < 0
                || (null != data && 0 != dataSize && dataOffset >= data.Length)
                || (null == data && dataOffset != 0))
            {
                throw new ArgumentOutOfRangeException(
                    "dataOffset",
                    dataOffset,
                    "must be inside the data buffer");
            }

            if ((null == data && dataSize > 0) || (null != data && dataSize > data.Length))
            {
                throw new ArgumentOutOfRangeException(
                    "dataSize",
                    dataSize,
                    "cannot be greater than the length of the data");
            }

            unsafe
            {
                fixed (byte* pointer = data)
                {
                    return Api.JetRetrieveColumn(
                        sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, out actualDataSize, grbit, retinfo);
                }
            }
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnAccessor" /> class.
 /// </summary>
 /// <param name="cursor">The cursor.</param>
 /// <param name="isamSession">The session.</param>
 /// <param name="tableid">The tableid.</param>
 /// <param name="grbit">The grbit.</param>
 internal ColumnAccessor(Cursor cursor, IsamSession isamSession, JET_TABLEID tableid, RetrieveColumnGrbit grbit)
 {
     this.cursor      = cursor;
     this.isamSession = isamSession;
     this.tableid     = tableid;
     this.grbit       = grbit;
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ColumnAccessor" /> class.
 /// </summary>
 /// <param name="cursor">The cursor.</param>
 /// <param name="isamSession">The session.</param>
 /// <param name="tableid">The tableid.</param>
 /// <param name="grbit">The grbit.</param>
 internal ColumnAccessor(Cursor cursor, IsamSession isamSession, JET_TABLEID tableid, RetrieveColumnGrbit grbit)
 {
     this.cursor = cursor;
     this.isamSession = isamSession;
     this.tableid = tableid;
     this.grbit = grbit;
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Validation for the requested retrieve options for the column.
 /// </summary>
 /// <param name="grbit">The retrieve options to validate.</param>
 protected virtual void ValidateRetrieveGrbit(RetrieveColumnGrbit grbit)
 {
     // We cannot support this request when there is no way to indicate that a column reference is returned.
     if ((grbit & (RetrieveColumnGrbit)0x00020000) != 0)  // UnpublishedGrbits.RetrieveAsRefIfNotInRecord
     {
         throw new EsentInvalidGrbitException();
     }
 }
Ejemplo n.º 5
0
        /// <summary>
        /// Retrieve a column from the current record as a DateTime
        /// </summary>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The data from the column.</returns>
        public virtual DateTime?RetrieveColumnAsDateTime(JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            this.Tracer.TraceVerbose("RetrieveColumn");
            this.CheckNotDisposed();
            if (0 == (RetrieveColumnGrbit.RetrieveCopy & grbit))
            {
                this.CheckHasCurrency();
            }

            return(Api.RetrieveColumnAsDateTime(this.session, this.table, columnid, grbit));
        }
Ejemplo n.º 6
0
        // retrieves all the columns from the record with JetRetrieveColumn
        private byte[][] GetColumnsWithJetRetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, RetrieveColumnGrbit grbit)
        {
            var data = new byte[this.columnInfos.Length][];

            for (int i = 0; i < this.columnInfos.Length; ++i)
            {
                data[i] = Api.RetrieveColumn(sesid, tableid, this.columnInfos[i].Columnid, grbit, null);
            }

            return(data);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Retrieves a boolean column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a boolean. Null if the column is null.</returns>
        public static bool?RetrieveColumnAsBoolean(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            byte?b = RetrieveColumnAsByte(sesid, tableid, columnid, grbit);

            if (b.HasValue)
            {
                return(0 != b.Value);
            }

            return(new bool?());
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Retrieve a column from the record.
        /// </summary>
        /// <param name="column">The column to retrieve.</param>
        /// <returns>The value of the column.</returns>
        private object RetrieveColumn(string column)
        {
            RetrieveColumnGrbit grbit = this.CurrentlyInUpdate ? RetrieveColumnGrbit.RetrieveCopy : RetrieveColumnGrbit.None;

            try
            {
                return(this.Table.Columns[column].RetrieveColumn(this.Cursor, grbit));
            }
            catch (KeyNotFoundException ex)
            {
                throw new EsentColumnNotFoundException(this.Table.TableName, column, ex);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Retrieves a datetime column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a datetime. Null if the column is null.</returns>
        public static DateTime?RetrieveColumnAsDateTime(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            // Internally DateTime is stored in OLE Automation format
            double?oadate = RetrieveColumnAsDouble(sesid, tableid, columnid, grbit);

            if (oadate.HasValue)
            {
                return(Conversions.ConvertDoubleToDateTime(oadate.Value));
            }

            return(new DateTime?());
        }
 /// <summary>
 /// A retrieve column function which always claims that the data in the column
 /// is larger than the passed in buffer.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// Retrieve options.
 /// </param>
 /// <returns>Always returns <see cref="JET_wrn.BufferTruncated"/>.</returns>
 private static int BadRetrieveColumn(
     JET_SESID sesid,
     JET_TABLEID tableid,
     JET_COLUMNID columnid,
     IntPtr data,
     int dataSize,
     out int actualDataSize,
     RetrieveColumnGrbit grbit,
     JET_RETINFO retinfo)
 {
     actualDataSize = (dataSize * 2) + (1024 * 1024);
     return((int)JET_wrn.BufferTruncated);
 }
Ejemplo n.º 11
0
 public static ulong?RetrieveColumnAsUInt64(
     JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
 {
     unsafe
     {
         const int DataSize = sizeof(ulong);
         ulong     data;
         var       pointer = new IntPtr(&data);
         int       actualDataSize;
         JET_wrn   wrn = JetRetrieveColumn(
             sesid, tableid, columnid, pointer, DataSize, out actualDataSize, grbit, null);
         return(CreateReturnValue(data, DataSize, wrn, actualDataSize));
     }
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>The data retrieved from the column. Null if the column is null.</returns>
        public static byte[] RetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one
            // chunk is a bit extreme!). Allocate a cached buffer and use that, allocating a larger one
            // if needed.
            byte[]  cache = Caches.ColumnCache.Allocate();
            byte[]  data  = cache;
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                // null column
                data = null;
            }
            else if (JET_wrn.Success == wrn)
            {
                data = MemoryCache.Duplicate(data, dataSize);
            }
            else
            {
                // there is more data to retrieve
                Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning", wrn.ToString());
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(
                    sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);
                if (JET_wrn.Success != wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            Caches.ColumnCache.Free(ref cache);
            return(data);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>The data retrieved from the column. Null if the column is null.</returns>
        public static byte[] RetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            // We expect most column values retrieved this way to be small (retrieving a 1GB LV as one
            // chunk is a bit extreme!). Allocate a small buffer and use that, allocating a larger one
            // if needed.
            var     data = new byte[256];
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                // null column
                data = null;
            }
            else
            {
                Array.Resize(ref data, dataSize);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    // there is more data to retrieve
                    wrn = JetRetrieveColumn(
                        sesid, tableid, columnid, data, data.Length, out dataSize, grbit, retinfo);
                    if (JET_wrn.Success != wrn)
                    {
                        string error = String.Format(
                            CultureInfo.CurrentCulture,
                            "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                            data.Length,
                            dataSize);
                        Trace.TraceError(error);
                        throw new InvalidOperationException(error);
                    }
                }
            }

            return(data);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Deserialize an object from a column.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to read from.</param>
        /// <param name="columnid">The column to read from.</param>
        /// <param name="grbit">The retrieval options to use.</param>
        /// <returns>The deserialized object. Null if the column was null.</returns>
        public static object DeserializeObjectFromColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            int actualSize;

            if (JET_wrn.ColumnNull == Api.JetRetrieveColumn(sesid, tableid, columnid, null, 0, out actualSize, grbit, null))
            {
                return(null);
            }

            using (var stream = new ColumnStream(sesid, tableid, columnid))
            {
                var deseriaizer = new BinaryFormatter();
                return(deseriaizer.Deserialize(stream));
            }
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Retrieves a single column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// Alternatively, this function can retrieve a column from a record being created
        /// in the cursor copy buffer. This function can also retrieve column data from an
        /// index entry that references the current record. In addition to retrieving the
        /// actual column value, JetRetrieveColumn can also be used to retrieve the size
        /// of a column, before retrieving the column data itself so that application
        /// buffers can be sized appropriately.
        /// </summary>
        /// <remarks>
        /// This is an internal method that takes a buffer offset as well as size.
        /// </remarks>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="data">The data buffer to be retrieved into.</param>
        /// <param name="dataSize">The size of the data buffer.</param>
        /// <param name="dataOffset">Offset into the data buffer to read data into.</param>
        /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <param name="retinfo">
        /// If pretinfo is give as NULL then the function behaves as though an itagSequence
        /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
        /// retrieve the first value of a multi-valued column, and to retrieve long data at
        /// offset 0 (zero).
        /// </param>
        /// <returns>An ESENT warning code.</returns>
        public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, int dataOffset, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
        {
            if (dataOffset < 0 ||
                (null != data && 0 != dataSize && dataOffset >= data.Length) ||
                (null == data && dataOffset != 0))
            {
                throw new ArgumentOutOfRangeException(
                          "dataOffset",
                          dataOffset,
                          "must be inside the data buffer");
            }

            if ((null == data && dataSize > 0) || (null != data && dataSize > data.Length))
            {
                throw new ArgumentOutOfRangeException(
                          "dataSize",
                          dataSize,
                          "cannot be greater than the length of the data");
            }

            unsafe
            {
                fixed(byte *pointer = data)
                {
                    return(Api.JetRetrieveColumn(
                               sesid, tableid, columnid, new IntPtr(pointer + dataOffset), dataSize, out actualDataSize, grbit, retinfo));
                }
            }
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Retrieves a single column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// Alternatively, this function can retrieve a column from a record being created
 /// in the cursor copy buffer. This function can also retrieve column data from an
 /// index entry that references the current record. In addition to retrieving the
 /// actual column value, JetRetrieveColumn can also be used to retrieve the size
 /// of a column, before retrieving the column data itself so that application
 /// buffers can be sized appropriately.
 /// </summary>
 /// <remarks>
 /// This is an internal-use version that takes an IntPtr.
 /// </remarks>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// If pretinfo is give as NULL then the function behaves as though an itagSequence
 /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
 /// retrieve the first value of a multi-valued column, and to retrieve long data at
 /// offset 0 (zero).
 /// </param>
 /// <returns>An ESENT warning code.</returns>
 internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
 {
     return(Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo)));
 }
 /// <summary>
 /// A retrieve column function which always claims that the data in the column
 /// is larger than the passed in buffer.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// Retrieve options.
 /// </param>
 /// <returns><see cref="JET_wrn.BufferTruncated"/>.</returns>
 private static int BadRetrieveColumn(
     JET_SESID sesid,
     JET_TABLEID tableid,
     JET_COLUMNID columnid,
     IntPtr data,
     int dataSize,
     out int actualDataSize,
     RetrieveColumnGrbit grbit,
     JET_RETINFO retinfo)
 {
     actualDataSize = (dataSize * 2) + (1024 * 1024);
     return (int)JET_wrn.BufferTruncated;
 }
Ejemplo n.º 18
0
        /// <summary>
        /// Retrieves a string column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding to use when converting data.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns>
        public static string RetrieveColumnAsString(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            JET_wrn wrn;

            // This is an optimization for retrieving small Unicode strings
            // We use a stack-allocated buffer to retrieve the data and then create
            // a string from the data
            if (Encoding.Unicode == encoding)
            {
                unsafe
                {
                    // 512 bytes give 256 Unicode characters.
                    const int BufferSize = 512;
                    char *    buffer     = stackalloc char[BufferSize];
                    int       actualDataSize;
                    wrn = JetRetrieveColumn(
                        sesid, tableid, columnid, new IntPtr(buffer), BufferSize, out actualDataSize, grbit, null);
                    if (JET_wrn.ColumnNull == wrn)
                    {
                        return(null);
                    }

                    if (JET_wrn.Success == wrn)
                    {
                        return(new string(buffer, 0, actualDataSize / sizeof(char)));
                    }

                    Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code");

                    // Fallthrough to normal case below
                }
            }

            // Retrieving a string happens in two stages: first the data is retrieved into a data
            // buffer and then the buffer is converted to a string. The buffer isn't needed for
            // very long so we try to use a cached buffer.
            byte[] cachedBuffer = memoryCache.Allocate();
            byte[] data         = cachedBuffer;

            int dataSize;

            wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.BufferTruncated == wrn)
            {
                Debug.Assert(dataSize > data.Length, "Expected column to be bigger than buffer");
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            // TODO: for Unicode strings pin the buffer and use the String(char*) constructor.
            string s = encoding.GetString(data, 0, dataSize);

            // Now we have extracted the string from the buffer we can free (cache) the buffer.
            memoryCache.Free(cachedBuffer);

            return(s);
        }
Ejemplo n.º 19
0
 /// <summary>
 /// Retrieves a single column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// Alternatively, this function can retrieve a column from a record being created
 /// in the cursor copy buffer. This function can also retrieve column data from an
 /// index entry that references the current record. In addition to retrieving the
 /// actual column value, JetRetrieveColumn can also be used to retrieve the size
 /// of a column, before retrieving the column data itself so that application
 /// buffers can be sized appropriately.  
 /// </summary>
 /// <remarks>
 /// This is an internal-use version that takes an IntPtr.
 /// </remarks>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// If pretinfo is give as NULL then the function behaves as though an itagSequence
 /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
 /// retrieve the first value of a multi-valued column, and to retrieve long data at
 /// offset 0 (zero).
 /// </param>
 /// <returns>An ESENT warning code.</returns>
 internal static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, IntPtr data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
 {
     return Api.Check(Impl.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, out actualDataSize, grbit, retinfo));
 }
Ejemplo n.º 20
0
        // retrieves all the columns from the record with JetRetrieveColumn
        private byte[][] GetColumnsWithJetRetrieveColumn(
            JET_SESID sesid, JET_TABLEID tableid, RetrieveColumnGrbit grbit)
        {
            var data = new byte[this.columnInfos.Length][];
            for (int i = 0; i < this.columnInfos.Length; ++i)
            {
                data[i] = Api.RetrieveColumn(sesid, tableid, this.columnInfos[i].Columnid, grbit, null);
            }

            return data;
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Retrieve a column from the current record as a String
        /// </summary>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding format.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The data from the column.</returns>
        public virtual string RetrieveColumnAsString(JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            this.Tracer.TraceVerbose("RetrieveColumn");
            this.CheckNotDisposed();
            if (0 == (RetrieveColumnGrbit.RetrieveCopy & grbit))
            {
                this.CheckHasCurrency();
            }

            return Api.RetrieveColumnAsString(this.session, this.table, columnid, encoding, grbit);
        }
Ejemplo n.º 22
0
 /// <summary>
 /// Retrieves a single column value from the current record. The record is that
 /// record associated with the index entry at the current position of the cursor.
 /// Alternatively, this function can retrieve a column from a record being created
 /// in the cursor copy buffer. This function can also retrieve column data from an
 /// index entry that references the current record. In addition to retrieving the
 /// actual column value, JetRetrieveColumn can also be used to retrieve the size
 /// of a column, before retrieving the column data itself so that application
 /// buffers can be sized appropriately.  
 /// </summary>
 /// <remarks>
 /// The RetrieveColumnAs functions provide datatype-specific retrieval functions.
 /// </remarks>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">The cursor to retrieve the column from.</param>
 /// <param name="columnid">The columnid to retrieve.</param>
 /// <param name="data">The data buffer to be retrieved into.</param>
 /// <param name="dataSize">The size of the data buffer.</param>
 /// <param name="actualDataSize">Returns the actual size of the data buffer.</param>
 /// <param name="grbit">Retrieve column options.</param>
 /// <param name="retinfo">
 /// If pretinfo is give as NULL then the function behaves as though an itagSequence
 /// of 1 and an ibLongValue of 0 (zero) were given. This causes column retrieval to
 /// retrieve the first value of a multi-valued column, and to retrieve long data at
 /// offset 0 (zero).
 /// </param>
 /// <returns>An ESENT warning code.</returns>
 public static JET_wrn JetRetrieveColumn(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, byte[] data, int dataSize, out int actualDataSize, RetrieveColumnGrbit grbit, JET_RETINFO retinfo)
 {
     return Api.JetRetrieveColumn(sesid, tableid, columnid, data, dataSize, 0, out actualDataSize, grbit, retinfo);
 }
Ejemplo n.º 23
0
        /// <summary>
        /// Перечислить значения в столбце со многоими значениями.
        /// </summary>
        /// <param name="table">Таблица.</param>
        /// <param name="columnid">Идентификатор столбца.</param>
        /// <param name="grbit">Флаг получения.</param>
        /// <returns>Результат.</returns>
        protected IEnumerable <T> EnumMultivalueColumn <T>(EsentTable table, JET_COLUMNID columnid, RetrieveColumnGrbit grbit = RetrieveColumnGrbit.None) where T : ColumnValue, new()
        {
            var count = GetMultiValueCount(table, columnid);

            if (count == 0)
            {
                yield break;
            }

            var a = new ColumnValue[1];

            for (var i = 1; i <= count; i++)
            {
                var col = new T
                {
                    ItagSequence  = i,
                    Columnid      = columnid,
                    RetrieveGrbit = grbit
                };
                a[0] = col;
                Api.RetrieveColumns(table.Session, table.Table, a);
                yield return(col);
            }
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Retrieves a string column value from the current record. The record is that
        /// record associated with the index entry at the current position of the cursor.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding to use when converting data.</param>
        /// <param name="grbit">Retrieval options.</param>
        /// <returns>The data retrieved from the column as a string. Null if the column is null.</returns>
        public static string RetrieveColumnAsString(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            // This is an optimization for retrieving Unicode strings
            if (Encoding.Unicode == encoding)
            {
                return(RetrieveUnicodeString(sesid, tableid, columnid, grbit));
            }

            // Retrieving a string happens in two stages: first the data is retrieved into a data
            // buffer and then the buffer is converted to a string. The buffer isn't needed for
            // very long so we try to use a cached buffer.
            byte[] cachedBuffer = Caches.ColumnCache.Allocate();
            byte[] data         = cachedBuffer;

            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);

            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.BufferTruncated == wrn)
            {
                Debug.Assert(dataSize > data.Length, "Expected column to be bigger than buffer");
                data = new byte[dataSize];
                wrn  = JetRetrieveColumn(sesid, tableid, columnid, data, data.Length, out dataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        data.Length,
                        dataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            // If we are about to decode ASCII data then use the UTF8 decoder instead. This
            // is done because the UTF8 decoder is faster and will produce the same results
            // on ASCII data. Different results will be produced on invalid data, but that
            // behaviour can be considered undefined.
            Encoding decoder = (encoding is ASCIIEncoding) ? asciiDecoder : encoding;
            string   s       = decoder.GetString(data, 0, dataSize);

            // Now we have extracted the string from the buffer we can free (cache) the buffer.
            Caches.ColumnCache.Free(ref cachedBuffer);

            return(s);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Retrieves the size of a single column value from the current record.
        /// The record is that record associated with the index entry at the
        /// current position of the cursor. Alternatively, this function can
        /// retrieve a column from a record being created in the cursor copy
        /// buffer. This function can also retrieve column data from an index
        /// entry that references the current record.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The cursor to retrieve the column from.</param>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="itagSequence">
        /// The sequence number of value in a multi-valued column.
        /// The array of values is one-based. The first value is
        /// sequence 1, not 0. If the record column has only one value then
        /// 1 should be passed as the itagSequence.
        /// </param>
        /// <param name="grbit">Retrieve column options.</param>
        /// <returns>The size of the column. 0 if the column is null.</returns>
        public static int?RetrieveColumnSize(
            JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, int itagSequence, RetrieveColumnGrbit grbit)
        {
            var retinfo = new JET_RETINFO {
                itagSequence = itagSequence
            };
            int     dataSize;
            JET_wrn wrn = JetRetrieveColumn(
                sesid, tableid, columnid, null, 0, out dataSize, grbit, retinfo);

            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            return(dataSize);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Retrieve a column from the current record as a String
        /// </summary>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="encoding">The string encoding format.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The data from the column.</returns>
        public virtual string RetrieveColumnAsString(JET_COLUMNID columnid, Encoding encoding, RetrieveColumnGrbit grbit)
        {
            this.Tracer.TraceVerbose("RetrieveColumn");
            this.CheckNotDisposed();
            if (0 == (RetrieveColumnGrbit.RetrieveCopy & grbit))
            {
                this.CheckHasCurrency();
            }

            return(Api.RetrieveColumnAsString(this.session, this.table, columnid, encoding, grbit));
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Retrieve a Unicode (UTF16) string. This is optimized to take advantage of the fact
        /// that no conversion is needed.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">The table to retrieve from.</param>
        /// <param name="columnid">The column to retrieve.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The string retrieved from the column.</returns>
        private static unsafe string RetrieveUnicodeString(JET_SESID sesid, JET_TABLEID tableid, JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            // 512 Unicode characters (1kb on stack)
            const int BufferSize = 512;
            char *    buffer     = stackalloc char[BufferSize];
            int       actualDataSize;
            JET_wrn   wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(buffer), BufferSize * sizeof(char), out actualDataSize, grbit, null);

            if (JET_wrn.ColumnNull == wrn)
            {
                return(null);
            }

            if (JET_wrn.Success == wrn)
            {
                ////return StringCache.GetString(buffer, 0, actualDataSize);
                return(new string(buffer, 0, actualDataSize / sizeof(char)));
            }

            Debug.Assert(JET_wrn.BufferTruncated == wrn, "Unexpected warning code");

            // Create a fake string of the appropriate size and then fill it in.
            var s = new string('\0', actualDataSize / sizeof(char));

            fixed(char *p = s)
            {
                int newDataSize;

                wrn = JetRetrieveColumn(sesid, tableid, columnid, new IntPtr(p), actualDataSize, out newDataSize, grbit, null);
                if (JET_wrn.BufferTruncated == wrn)
                {
                    string error = String.Format(
                        CultureInfo.CurrentCulture,
                        "Column size changed from {0} to {1}. The record was probably updated by another thread.",
                        actualDataSize,
                        newDataSize);
                    Trace.TraceError(error);
                    throw new InvalidOperationException(error);
                }
            }

            return(s);
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Retrieve a column from the current record as a UInt64
        /// </summary>
        /// <param name="columnid">The columnid to retrieve.</param>
        /// <param name="grbit">Retrieve options.</param>
        /// <returns>The data from the column.</returns>
        public virtual ulong? RetrieveColumnAsUInt64(JET_COLUMNID columnid, RetrieveColumnGrbit grbit)
        {
            this.Tracer.TraceVerbose("RetrieveColumn");
            this.CheckNotDisposed();
            if (0 == (RetrieveColumnGrbit.RetrieveCopy & grbit))
            {
                this.CheckHasCurrency();
            }

            return Api.RetrieveColumnAsUInt64(this.session, this.table, columnid, grbit);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Gets the fields of the current row.
        /// </summary>
        /// <param name="grbit">The grbit.</param>
        /// <returns>A <see cref="FieldCollection"/> object to allow retrieval of all fields of the current row.</returns>
        internal FieldCollection GetFields(RetrieveColumnGrbit grbit)
        {
            JET_PFNREALLOC allocator =
                (context, pv, cb) =>
                IntPtr.Zero == pv ? Marshal.AllocHGlobal(new IntPtr(cb)) : Marshal.ReAllocHGlobal(pv, new IntPtr(cb));

            lock (this.isamSession)
            {
                this.CheckDisposed();
                this.CheckRecord();

                EnumerateColumnsGrbit enumerateGrbit = ((grbit & RetrieveColumnGrbit.RetrieveCopy) != 0)
                                                           ? EnumerateColumnsGrbit.EnumerateCopy
                                                           : EnumerateColumnsGrbit.None;

                using (IsamTransaction trx = new IsamTransaction(this.isamSession, true))
                {
                    // enumerate all field values in the current record or copy
                    // buffer
                    JET_ENUMCOLUMN[] jecs;
                    int numColumnValues;
                    Api.JetEnumerateColumns(
                        this.isamSession.Sesid,
                        this.tableid,
                        0, // numColumnids
                        null, // columnids
                        out numColumnValues,
                        out jecs,
                        allocator,
                        IntPtr.Zero, // allocatorContext,
                        int.MaxValue,
                        enumerateGrbit);

                    // create a field collection to contain our field values
                    FieldCollection fields = new FieldCollection();

                    // save the location of the source record for these field values
                    fields.Location = this.Location;

                    // fill the field collection with our field values
                    if (jecs != null && jecs.Length > 0)
                    {
                        foreach (JET_ENUMCOLUMN jec in jecs)
                        {
                            if (jec.rgEnumColumnValue != null && jec.rgEnumColumnValue.Length > 0)
                            {
                                JET_COLUMNBASE columnbase;
                                VistaApi.JetGetTableColumnInfo(
                                    this.isamSession.Sesid,
                                    this.tableid,
                                    jec.columnid,
                                    out columnbase);

                                Columnid columnid = new Columnid(columnbase);
                                bool isAscii = columnbase.cp == JET_CP.ASCII;
                                FieldValueCollection values = new FieldValueCollection(columnid);
                                foreach (JET_ENUMCOLUMNVALUE jecv in jec.rgEnumColumnValue)
                                {
                                    // FUTURE-2013/11/15-martinc: Drat, this is an IntPtr, and ObjectFromBytes() really
                                    // wants a byte[] array. Copying the data to a byte array just to simply
                                    // re-interpret it as an object is inefficient.
                                    // We should write Converter.ObjectFromIntPtr...
                                    byte[] bytesData = new byte[jecv.cbData];
                                    Marshal.Copy(jecv.pvData, bytesData, 0, bytesData.Length);

                                    values.Add(Converter.ObjectFromBytes(columnbase.coltyp, isAscii, bytesData));
                                }

                                values.ReadOnly = true;
                                fields.Add(values);
                            }
                        }
                    }

                    fields.ReadOnly = true;

                    // Return the field collection.
                    return fields;
                }
            }
        }