wasCSharpSQLite – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | using Bitmask = System.UInt64; |
||
6 | using u8 = System.Byte; |
||
7 | using u16 = System.UInt16; |
||
8 | using u32 = System.UInt32; |
||
9 | |||
10 | namespace Community.CsharpSqlite |
||
11 | { |
||
12 | public partial class Sqlite3 |
||
13 | { |
||
14 | /* |
||
15 | ** 2009 November 25 |
||
16 | ** |
||
17 | ** The author disclaims copyright to this source code. In place of |
||
18 | ** a legal notice, here is a blessing: |
||
19 | ** |
||
20 | ** May you do good and not evil. |
||
21 | ** May you find forgiveness for yourself and forgive others. |
||
22 | ** May you share freely, never taking more than you give. |
||
23 | ** |
||
24 | ************************************************************************* |
||
25 | ** |
||
26 | ** This file contains code used to insert the values of host parameters |
||
27 | ** (aka "wildcards") into the SQL text output by sqlite3_trace(). |
||
28 | ************************************************************************* |
||
29 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
30 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
31 | ** |
||
32 | ** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e |
||
33 | ** |
||
34 | ************************************************************************* |
||
35 | */ |
||
36 | //#include "sqliteInt.h" |
||
37 | //#include "vdbeInt.h" |
||
38 | |||
39 | #if !SQLITE_OMIT_TRACE |
||
40 | |||
41 | /* |
||
42 | ** zSql is a zero-terminated string of UTF-8 SQL text. Return the number of |
||
43 | ** bytes in this text up to but excluding the first character in |
||
44 | ** a host parameter. If the text contains no host parameters, return |
||
45 | ** the total number of bytes in the text. |
||
46 | */ |
||
47 | static int findNextHostParameter( string zSql, int iOffset, ref int pnToken ) |
||
48 | { |
||
49 | int tokenType = 0; |
||
50 | int nTotal = 0; |
||
51 | int n; |
||
52 | |||
53 | pnToken = 0; |
||
54 | while ( iOffset < zSql.Length ) |
||
55 | { |
||
56 | n = sqlite3GetToken( zSql, iOffset, ref tokenType ); |
||
57 | Debug.Assert( n > 0 && tokenType != TK_ILLEGAL ); |
||
58 | if ( tokenType == TK_VARIABLE ) |
||
59 | { |
||
60 | pnToken = n; |
||
61 | break; |
||
62 | } |
||
63 | nTotal += n; |
||
64 | iOffset += n;// zSql += n; |
||
65 | } |
||
66 | return nTotal; |
||
67 | } |
||
68 | |||
69 | /* |
||
70 | ** This function returns a pointer to a nul-terminated string in memory |
||
71 | ** obtained from sqlite3DbMalloc(). If sqlite3.vdbeExecCnt is 1, then the |
||
72 | ** string contains a copy of zRawSql but with host parameters expanded to |
||
73 | ** their current bindings. Or, if sqlite3.vdbeExecCnt is greater than 1, |
||
74 | ** then the returned string holds a copy of zRawSql with "-- " prepended |
||
75 | ** to each line of text. |
||
76 | ** |
||
77 | ** The calling function is responsible for making sure the memory returned |
||
78 | ** is eventually freed. |
||
79 | ** |
||
80 | ** ALGORITHM: Scan the input string looking for host parameters in any of |
||
81 | ** these forms: ?, ?N, $A, @A, :A. Take care to avoid text within |
||
82 | ** string literals, quoted identifier names, and comments. For text forms, |
||
83 | ** the host parameter index is found by scanning the perpared |
||
84 | ** statement for the corresponding OP_Variable opcode. Once the host |
||
85 | ** parameter index is known, locate the value in p->aVar[]. Then render |
||
86 | ** the value as a literal in place of the host parameter name. |
||
87 | */ |
||
88 | static string sqlite3VdbeExpandSql( |
||
89 | Vdbe p, /* The prepared statement being evaluated */ |
||
90 | string zRawSql /* Raw text of the SQL statement */ |
||
91 | ) |
||
92 | { |
||
93 | sqlite3 db; /* The database connection */ |
||
94 | int idx = 0; /* Index of a host parameter */ |
||
95 | int nextIndex = 1; /* Index of next ? host parameter */ |
||
96 | int n; /* Length of a token prefix */ |
||
97 | int nToken = 0; /* Length of the parameter token */ |
||
98 | int i; /* Loop counter */ |
||
99 | Mem pVar; /* Value of a host parameter */ |
||
100 | StrAccum _out = new StrAccum( 1000 ); /* Accumulate the _output here */ |
||
101 | ////StringBuilder zBase = new StringBuilder( 100 ); /* Initial working space */ |
||
102 | int izRawSql = 0; |
||
103 | |||
104 | db = p.db; |
||
105 | sqlite3StrAccumInit( _out, null, 100, |
||
106 | db.aLimit[SQLITE_LIMIT_LENGTH] ); |
||
107 | _out.db = db; |
||
108 | if ( db.vdbeExecCnt > 1 ) |
||
109 | { |
||
110 | while ( izRawSql < zRawSql.Length ) |
||
111 | { |
||
112 | //string zStart = zRawSql; |
||
113 | while ( zRawSql[izRawSql++] != '\n' && izRawSql < zRawSql.Length ) |
||
114 | ; |
||
115 | sqlite3StrAccumAppend( _out, "-- ", 3 ); |
||
116 | sqlite3StrAccumAppend( _out, zRawSql, (int)izRawSql );//zRawSql - zStart ); |
||
117 | } |
||
118 | } |
||
119 | else |
||
120 | { |
||
121 | while ( izRawSql < zRawSql.Length ) |
||
122 | { |
||
123 | n = findNextHostParameter( zRawSql, izRawSql, ref nToken ); |
||
124 | Debug.Assert( n > 0 ); |
||
125 | sqlite3StrAccumAppend( _out, zRawSql.Substring( izRawSql, n ), n ); |
||
126 | izRawSql += n; |
||
127 | Debug.Assert( izRawSql < zRawSql.Length || nToken == 0 ); |
||
128 | if ( nToken == 0 ) |
||
129 | break; |
||
130 | if ( zRawSql[izRawSql] == '?' ) |
||
131 | { |
||
132 | if ( nToken > 1 ) |
||
133 | { |
||
134 | Debug.Assert( sqlite3Isdigit( zRawSql[izRawSql + 1] ) ); |
||
135 | sqlite3GetInt32( zRawSql, izRawSql + 1, ref idx ); |
||
136 | } |
||
137 | else |
||
138 | { |
||
139 | idx = nextIndex; |
||
140 | } |
||
141 | } |
||
142 | else |
||
143 | { |
||
144 | Debug.Assert( zRawSql[izRawSql] == ':' || zRawSql[izRawSql] == '$' || zRawSql[izRawSql] == '@' ); |
||
145 | testcase( zRawSql[izRawSql] == ':' ); |
||
146 | testcase( zRawSql[izRawSql] == '$' ); |
||
147 | testcase( zRawSql[izRawSql] == '@' ); |
||
148 | idx = sqlite3VdbeParameterIndex( p, zRawSql.Substring( izRawSql, nToken ), nToken ); |
||
149 | Debug.Assert( idx > 0 ); |
||
150 | } |
||
151 | izRawSql += nToken; |
||
152 | nextIndex = idx + 1; |
||
153 | Debug.Assert( idx > 0 && idx <= p.nVar ); |
||
154 | pVar = p.aVar[idx - 1]; |
||
155 | if ( ( pVar.flags & MEM_Null ) != 0 ) |
||
156 | { |
||
157 | sqlite3StrAccumAppend( _out, "NULL", 4 ); |
||
158 | } |
||
159 | else if ( ( pVar.flags & MEM_Int ) != 0 ) |
||
160 | { |
||
161 | sqlite3XPrintf( _out, "%lld", pVar.u.i ); |
||
162 | } |
||
163 | else if ( ( pVar.flags & MEM_Real ) != 0 ) |
||
164 | { |
||
165 | sqlite3XPrintf( _out, "%!.15g", pVar.r ); |
||
166 | } |
||
167 | else if ( ( pVar.flags & MEM_Str ) != 0 ) |
||
168 | { |
||
169 | #if !SQLITE_OMIT_UTF16 |
||
170 | u8 enc = ENC(db); |
||
171 | if( enc!=SQLITE_UTF8 ){ |
||
172 | Mem utf8; |
||
173 | memset(&utf8, 0, sizeof(utf8)); |
||
174 | utf8.db = db; |
||
175 | sqlite3VdbeMemSetStr(&utf8, pVar.z, pVar.n, enc, SQLITE_STATIC); |
||
176 | sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8); |
||
177 | sqlite3XPrintf(_out, "'%.*q'", utf8.n, utf8.z); |
||
178 | sqlite3VdbeMemRelease(&utf8); |
||
179 | }else |
||
180 | #endif |
||
181 | { |
||
182 | sqlite3XPrintf( _out, "'%.*q'", pVar.n, pVar.z ); |
||
183 | } |
||
184 | } |
||
185 | else if ( ( pVar.flags & MEM_Zero ) != 0 ) |
||
186 | { |
||
187 | sqlite3XPrintf( _out, "zeroblob(%d)", pVar.u.nZero ); |
||
188 | } |
||
189 | else |
||
190 | { |
||
191 | Debug.Assert( ( pVar.flags & MEM_Blob ) != 0 ); |
||
192 | sqlite3StrAccumAppend( _out, "x'", 2 ); |
||
193 | for ( i = 0; i < pVar.n; i++ ) |
||
194 | { |
||
195 | sqlite3XPrintf( _out, "%02x", pVar.zBLOB[i] & 0xff ); |
||
196 | } |
||
197 | sqlite3StrAccumAppend( _out, "'", 1 ); |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | return sqlite3StrAccumFinish( _out ); |
||
202 | } |
||
203 | |||
204 | #endif //* #if !SQLITE_OMIT_TRACE */ |
||
205 | } |
||
206 | } |