Exemple #1
0
        /// <summary>
        /// Recursive RetrieveColumns method for data pinning. This should pin a buffer and
        /// call the inherited RetrieveColumns method.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">
        /// The table to retrieve the columns from.
        /// </param>
        /// <param name="columnValues">
        /// Column values to retrieve.
        /// </param>
        internal static void RetrieveColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues)
        {
            const int MaxColumnValues = 1024;

            if (columnValues.Length > MaxColumnValues)
            {
                throw new ArgumentOutOfRangeException("columnValues", columnValues.Length, "Too many column values");
            }

            unsafe
            {
                byte[] buffer = null;
                NATIVE_RETRIEVECOLUMN *nativeRetrievecolumns = stackalloc NATIVE_RETRIEVECOLUMN[columnValues.Length];

                try
                {
                    buffer = Caches.ColumnCache.Allocate();
                    Debug.Assert(MaxColumnValues * 16 < buffer.Length, "Maximum size of fixed columns could exceed buffer size");

                    fixed(byte *pinnedBuffer = buffer)
                    {
                        byte *currentBuffer            = pinnedBuffer;
                        int   numVariableLengthColumns = columnValues.Length;

                        // First the fixed-size columns
                        for (int i = 0; i < columnValues.Length; ++i)
                        {
                            if (0 != columnValues[i].Size)
                            {
                                columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
                                nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
                                nativeRetrievecolumns[i].cbData = checked ((uint)columnValues[i].Size);

                                currentBuffer += nativeRetrievecolumns[i].cbData;
                                Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");

                                numVariableLengthColumns--;
                            }
                        }

                        // Now the variable-length columns
                        if (numVariableLengthColumns > 0)
                        {
                            int bufferUsed      = checked ((int)(currentBuffer - pinnedBuffer));
                            int bufferRemaining = checked (buffer.Length - bufferUsed);
                            int bufferPerColumn = bufferRemaining / numVariableLengthColumns;
                            Debug.Assert(bufferPerColumn > 0, "Not enough buffer left to retrieve variable length columns");

                            // Now the variable-size columns
                            for (int i = 0; i < columnValues.Length; ++i)
                            {
                                if (0 == columnValues[i].Size)
                                {
                                    columnValues[i].MakeNativeRetrieveColumn(ref nativeRetrievecolumns[i]);
                                    nativeRetrievecolumns[i].pvData = new IntPtr(currentBuffer);
                                    nativeRetrievecolumns[i].cbData = checked ((uint)bufferPerColumn);
                                    currentBuffer += nativeRetrievecolumns[i].cbData;
                                    Debug.Assert(currentBuffer <= pinnedBuffer + buffer.Length, "Moved past end of pinned buffer");
                                }
                            }
                        }

                        // Retrieve the columns
                        Api.Check(Api.Impl.JetRetrieveColumns(sesid, tableid, nativeRetrievecolumns, columnValues.Length));

                        // Propagate the warnings and output.
                        for (int i = 0; i < columnValues.Length; ++i)
                        {
                            columnValues[i].Error        = (JET_wrn)nativeRetrievecolumns[i].err;
                            columnValues[i].ItagSequence = (int)nativeRetrievecolumns[i].itagSequence;
                        }

                        // Now parse out the columns that were retrieved successfully
                        for (int i = 0; i < columnValues.Length; ++i)
                        {
                            if (nativeRetrievecolumns[i].err != (int)JET_wrn.BufferTruncated)
                            {
                                byte *columnBuffer = (byte *)nativeRetrievecolumns[i].pvData;
                                int   startIndex   = checked ((int)(columnBuffer - pinnedBuffer));
                                columnValues[i].GetValueFromBytes(
                                    buffer,
                                    startIndex,
                                    checked ((int)nativeRetrievecolumns[i].cbActual),
                                    nativeRetrievecolumns[i].err);
                            }
                        }
                    }

                    // Finally retrieve the buffers where the columns weren't large enough.
                    RetrieveTruncatedBuffers(sesid, tableid, columnValues, nativeRetrievecolumns);
                }
                finally
                {
                    if (buffer != null)
                    {
                        Caches.ColumnCache.Free(ref buffer);
                    }
                }
            }
        }
Exemple #2
0
 /// <summary>
 /// Recursive SetColumns method for data pinning. This should populate the buffer and
 /// call the inherited SetColumns method.
 /// </summary>
 /// <param name="sesid">The session to use.</param>
 /// <param name="tableid">
 /// The table to set the columns in. An update should be prepared.
 /// </param>
 /// <param name="columnValues">
 /// Column values to set.
 /// </param>
 /// <param name="nativeColumns">
 /// Structures to put the pinned data in.
 /// </param>
 /// <param name="i">Offset of this object in the array.</param>
 /// <returns>An error code.</returns>
 internal abstract unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN *nativeColumns, int i);
Exemple #3
0
        /// <summary>
        /// Recursive SetColumns method for data pinning. This populates the buffer and
        /// calls the inherited SetColumns method.
        /// </summary>
        /// <param name="sesid">The session to use.</param>
        /// <param name="tableid">
        /// The table to set the columns in. An update should be prepared.
        /// </param>
        /// <param name="columnValues">
        /// Column values to set.
        /// </param>
        /// <param name="nativeColumns">
        /// Structures to put the pinned data in.
        /// </param>
        /// <param name="i">Offset of this object in the array.</param>
        /// <returns>An error code.</returns>
        internal override unsafe int SetColumns(JET_SESID sesid, JET_TABLEID tableid, ColumnValue[] columnValues, NATIVE_SETCOLUMN *nativeColumns, int i)
        {
            var data = this.Value.GetValueOrDefault();

            return(this.SetColumns(sesid, tableid, columnValues, nativeColumns, i, &data, sizeof(double), this.Value.HasValue));
        }