File: DbDataRecord.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (150 lines) | stat: -rw-r--r-- 5,444 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//------------------------------------------------------------------------------
// <copyright file="DbDataRecord.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;            //Component
using System.Data;
using System.Runtime.InteropServices;   //Marshal
using System.Reflection;                //Missing

namespace System.Data.Odbc {
    sealed internal class DbSchemaInfo {

        internal DbSchemaInfo() {
        }

        internal string _name;
        internal string _typename;
        internal Type _type;
        internal ODBC32.SQL_TYPE? _dbtype;
        internal object _scale;
        internal object _precision;

        // extension to allow BindCol
        //
        internal int _columnlength;          //
        internal int _valueOffset;           // offset to the data in the row buffer
        internal int _lengthOffset;          // offset to the length in the row buffer
        internal ODBC32.SQL_C _sqlctype;         // need this to bind the value
        internal ODBC32.SQL_TYPE _sql_type;      // need that to properly marshal the value
    }

    /////////////////////////////////////////////////////////////////////////////
    // Cache
    //
    //  This is a on-demand cache, only caching what the user requests.
    //  The reational is that for ForwardOnly access (the default and LCD of drivers)
    //  we cannot obtain the data more than once, and even GetData(0) (to determine is-null)
    //  still obtains data for fixed lenght types.

    //  So simple code like:
    //      if(!rReader.IsDBNull(i))
    //          rReader.GetInt32(i)
    //
    //  Would fail, unless we cache on the IsDBNull call, and return the cached
    //  item for GetInt32.  This actually improves perf anyway, (even if the driver could
    //  support it), since we are not making a seperate interop call...

    //  We do not cache all columns, so reading out of order is still not
    //
    /////////////////////////////////////////////////////////////////////////////
    sealed internal class DbCache {
        //Data

        private bool[] _isBadValue;
        private DbSchemaInfo[] _schema;
        private object[] _values;
        private OdbcDataReader _record;
        internal int _count;
        internal bool _randomaccess = true;

        //Constructor
        internal DbCache(OdbcDataReader record, int count) {
            _count = count;
            _record = record;
            _randomaccess = (!record.IsBehavior(CommandBehavior.SequentialAccess));
            _values = new object[count];
            _isBadValue = new bool[count];
        }

        //Accessor
        internal object this[int i] {
            get {
                if(_isBadValue[i]) {
                    OverflowException innerException = (OverflowException)Values[i];
                    throw new OverflowException(innerException.Message, innerException);
                }
                return Values[i];
            }
            set {
                Values[i] = value;
                _isBadValue[i] = false;
            }
        }

        internal int Count {
            get {
                return _count;
            }
        }

        internal void InvalidateValue(int i) {
            _isBadValue[i] = true;
        }

        internal object[] Values {
            get {
                return _values;
            }
        }

        internal object AccessIndex(int i) {
            //Note: We could put this directly in this[i], instead of having an explicit overload.
            //However that means that EVERY access into the cache takes the hit of checking, so
            //something as simple as the following code would take two hits.  It's nice not to
            //have to take the hit when you know what your doing.
            //
            //  if(cache[i] == null)
            //      ....
            //  return cache[i];

            object[] values = this.Values;
            if(_randomaccess) {
                //Random
                //Means that the user can ask for the values int any order (ie: out of order).
                //  In order to acheive this on a forward only stream, we need to actually
                //  retreive all the value in between so they can go back to values they've skipped
                for(int c = 0; c < i; c++) {
                    if(values[c] == null) {
                        values[c] = _record.GetValue(c);
                    }
                }
            }
            return values[i];
        }

        internal DbSchemaInfo GetSchema(int i) {
            if(_schema == null) {
                _schema = new DbSchemaInfo[Count];
            }
            if(_schema[i] == null) {
                _schema[i] = new DbSchemaInfo();
            }
            return _schema[i];
        }

        internal void FlushValues() {
            //Set all objects to null (to explcitly release them)
            //Note: SchemaInfo remains the same for all rows - no need to reget those...
            int count = _values.Length;
            for(int i = 0; i < count; ++i) {
                _values[i] = null;
            }
        }
    }
}