wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System.Diagnostics; |
2 | using unsigned = System.UInt32; |
||
3 | using sqlite_int64 = System.Int64; |
||
4 | using sqlite3_int64 = System.Int64; |
||
5 | using sqlite3_value_int64 = System.Int64; |
||
6 | |||
7 | namespace Community.CsharpSqlite |
||
8 | { |
||
9 | #if TCLSH |
||
10 | using tcl.lang; |
||
11 | using sqlite3_stmt = Sqlite3.Vdbe; |
||
12 | using sqlite3_value = Sqlite3.Mem; |
||
13 | using Tcl_Interp = tcl.lang.Interp; |
||
14 | using Tcl_Obj = tcl.lang.TclObject; |
||
15 | using ClientData = System.Object; |
||
16 | |||
17 | public partial class Sqlite3 |
||
18 | { |
||
19 | /* |
||
20 | ** 2011 April 02 |
||
21 | ** |
||
22 | ** The author disclaims copyright to this source code. In place of |
||
23 | ** a legal notice, here is a blessing: |
||
24 | ** |
||
25 | ** May you do good and not evil. |
||
26 | ** May you find forgiveness for yourself and forgive others. |
||
27 | ** May you share freely, never taking more than you give. |
||
28 | ** |
||
29 | ************************************************************************* |
||
30 | ** |
||
31 | ** This file implements a virtual table that returns the whole numbers |
||
32 | ** between 1 and 4294967295, inclusive. |
||
33 | ** |
||
34 | ** Example: |
||
35 | ** |
||
36 | ** CREATE VIRTUAL TABLE nums USING wholenumber; |
||
37 | ** SELECT value FROM nums WHERE value<10; |
||
38 | ** |
||
39 | ** Results in: |
||
40 | ** |
||
41 | ** 1 2 3 4 5 6 7 8 9 |
||
42 | */ |
||
43 | //#include "sqlite3.h" |
||
44 | //#include <assert.h> |
||
45 | //#include <string.h> |
||
46 | |||
47 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
48 | |||
49 | |||
50 | /* A wholenumber cursor object */ |
||
51 | //typedef struct wholenumber_cursor wholenumber_cursor; |
||
52 | class wholenumber_cursor : sqlite3_vtab_cursor |
||
53 | { |
||
54 | //public sqlite3_vtab_cursor base; /* Base class - must be first */ |
||
55 | public unsigned iValue; /* Current value */ |
||
56 | public unsigned mxValue; /* Maximum value */ |
||
57 | }; |
||
58 | |||
59 | /* Methods for the wholenumber module */ |
||
60 | static int wholenumberConnect( |
||
61 | sqlite3 db, |
||
62 | object pAux, |
||
63 | int argc, string[] argv, |
||
64 | out sqlite3_vtab ppVtab, |
||
65 | out string pzErr |
||
66 | ) |
||
67 | { |
||
68 | sqlite3_vtab pNew; |
||
69 | pNew = ppVtab = new sqlite3_vtab();//sqlite3_malloc( sizeof(*pNew) ); |
||
70 | //if ( pNew == null ) |
||
71 | // return SQLITE_NOMEM; |
||
72 | sqlite3_declare_vtab( db, "CREATE TABLE x(value)" ); |
||
73 | //memset(pNew, 0, sizeof(*pNew)); |
||
74 | pzErr = ""; |
||
75 | return SQLITE_OK; |
||
76 | } |
||
77 | /* Note that for this virtual table, the xCreate and xConnect |
||
78 | ** methods are identical. */ |
||
79 | |||
80 | static int wholenumberDisconnect( ref object pVtab ) |
||
81 | { |
||
82 | pVtab = null;// sqlite3_free( pVtab ); |
||
83 | return SQLITE_OK; |
||
84 | } |
||
85 | /* The xDisconnect and xDestroy methods are also the same */ |
||
86 | |||
87 | |||
88 | /* |
||
89 | ** Open a new wholenumber cursor. |
||
90 | */ |
||
91 | static int wholenumberOpen( sqlite3_vtab p, out sqlite3_vtab_cursor ppCursor ) |
||
92 | { |
||
93 | wholenumber_cursor pCur; |
||
94 | pCur = new wholenumber_cursor();//sqlite3_malloc( sizeof(*pCur) ); |
||
95 | //if ( pCur == null ) |
||
96 | // return SQLITE_NOMEM; |
||
97 | //memset(pCur, 0, sizeof(*pCur)); |
||
98 | ppCursor = pCur;//.base; |
||
99 | return SQLITE_OK; |
||
100 | } |
||
101 | |||
102 | /* |
||
103 | ** Close a wholenumber cursor. |
||
104 | */ |
||
105 | static int wholenumberClose( ref sqlite3_vtab_cursor cur ) |
||
106 | { |
||
107 | cur = null;// sqlite3_free( ref cur ); |
||
108 | return SQLITE_OK; |
||
109 | } |
||
110 | |||
111 | |||
112 | /* |
||
113 | ** Advance a cursor to its next row of output |
||
114 | */ |
||
115 | static int wholenumberNext( sqlite3_vtab_cursor cur ) |
||
116 | { |
||
117 | wholenumber_cursor pCur = (wholenumber_cursor)cur; |
||
118 | pCur.iValue++; |
||
119 | return SQLITE_OK; |
||
120 | } |
||
121 | |||
122 | /* |
||
123 | ** Return the value associated with a wholenumber. |
||
124 | */ |
||
125 | static int wholenumberColumn( |
||
126 | sqlite3_vtab_cursor cur, |
||
127 | sqlite3_context ctx, |
||
128 | int i |
||
129 | ) |
||
130 | { |
||
131 | wholenumber_cursor pCur = (wholenumber_cursor)cur; |
||
132 | sqlite3_result_int64( ctx, pCur.iValue ); |
||
133 | return SQLITE_OK; |
||
134 | } |
||
135 | |||
136 | /* |
||
137 | ** The rowid. |
||
138 | */ |
||
139 | static int wholenumberRowid( sqlite3_vtab_cursor cur, out sqlite_int64 pRowid ) |
||
140 | { |
||
141 | wholenumber_cursor pCur = (wholenumber_cursor)cur; |
||
142 | pRowid = pCur.iValue; |
||
143 | return SQLITE_OK; |
||
144 | } |
||
145 | |||
146 | /* |
||
147 | ** When the wholenumber_cursor.rLimit value is 0 or less, that is a signal |
||
148 | ** that the cursor has nothing more to output. |
||
149 | */ |
||
150 | static int wholenumberEof( sqlite3_vtab_cursor cur ) |
||
151 | { |
||
152 | wholenumber_cursor pCur = (wholenumber_cursor)cur; |
||
153 | return ( pCur.iValue > pCur.mxValue || pCur.iValue == 0 ) ? 1 : 0; |
||
154 | } |
||
155 | |||
156 | /* |
||
157 | ** Called to "rewind" a cursor back to the beginning so that |
||
158 | ** it starts its output over again. Always called at least once |
||
159 | ** prior to any wholenumberColumn, wholenumberRowid, or wholenumberEof call. |
||
160 | ** |
||
161 | ** idxNum Constraints |
||
162 | ** ------ --------------------- |
||
163 | ** 0 (none) |
||
164 | ** 1 value > $argv0 |
||
165 | ** 2 value >= $argv0 |
||
166 | ** 4 value < $argv0 |
||
167 | ** 8 value <= $argv0 |
||
168 | ** |
||
169 | ** 5 value > $argv0 AND value < $argv1 |
||
170 | ** 6 value >= $argv0 AND value < $argv1 |
||
171 | ** 9 value > $argv0 AND value <= $argv1 |
||
172 | ** 10 value >= $argv0 AND value <= $argv1 |
||
173 | */ |
||
174 | static int wholenumberFilter( |
||
175 | sqlite3_vtab_cursor pVtabCursor, |
||
176 | int idxNum, string idxStr, |
||
177 | int argc, sqlite3_value[] argv |
||
178 | ) |
||
179 | { |
||
180 | wholenumber_cursor pCur = (wholenumber_cursor)pVtabCursor; |
||
181 | sqlite3_int64 v; |
||
182 | int i = 0; |
||
183 | pCur.iValue = 1; |
||
184 | pCur.mxValue = 0xffffffff; /* 4294967295 */ |
||
185 | if ( ( idxNum & 3 ) != 0 ) |
||
186 | { |
||
187 | v = sqlite3_value_int64( argv[0] ) + ( idxNum & 1 ); |
||
188 | if ( v > pCur.iValue && v <= pCur.mxValue ) |
||
189 | pCur.iValue = (uint)v; |
||
190 | i++; |
||
191 | } |
||
192 | if ( ( idxNum & 12 ) != 0 ) |
||
193 | { |
||
194 | v = sqlite3_value_int64( argv[i] ) - ( ( idxNum >> 2 ) & 1 ); |
||
195 | if ( v >= pCur.iValue && v < pCur.mxValue ) |
||
196 | pCur.mxValue = (uint)v; |
||
197 | } |
||
198 | return SQLITE_OK; |
||
199 | } |
||
200 | |||
201 | /* |
||
202 | ** Search for terms of these forms: |
||
203 | ** |
||
204 | ** (1) value > $value |
||
205 | ** (2) value >= $value |
||
206 | ** (4) value < $value |
||
207 | ** (8) value <= $value |
||
208 | ** |
||
209 | ** idxNum is an ORed combination of 1 or 2 with 4 or 8. |
||
210 | */ |
||
211 | static int wholenumberBestIndex( |
||
212 | sqlite3_vtab vtab, |
||
213 | ref sqlite3_index_info pIdxInfo |
||
214 | ) |
||
215 | { |
||
216 | int i; |
||
217 | int idxNum = 0; |
||
218 | int argvIdx = 1; |
||
219 | int ltIdx = -1; |
||
220 | int gtIdx = -1; |
||
221 | sqlite3_index_constraint pConstraint; |
||
222 | //pConstraint = pIdxInfo.aConstraint; |
||
223 | for ( i = 0; i < pIdxInfo.nConstraint; i++ )//, pConstraint++) |
||
224 | { |
||
225 | pConstraint = pIdxInfo.aConstraint[i]; |
||
226 | if ( pConstraint.usable == false ) |
||
227 | continue; |
||
228 | if ( ( idxNum & 3 ) == 0 && pConstraint.op == SQLITE_INDEX_CONSTRAINT_GT ) |
||
229 | { |
||
230 | idxNum |= 1; |
||
231 | ltIdx = i; |
||
232 | } |
||
233 | if ( ( idxNum & 3 ) == 0 && pConstraint.op == SQLITE_INDEX_CONSTRAINT_GE ) |
||
234 | { |
||
235 | idxNum |= 2; |
||
236 | ltIdx = i; |
||
237 | } |
||
238 | if ( ( idxNum & 12 ) == 0 && pConstraint.op == SQLITE_INDEX_CONSTRAINT_LT ) |
||
239 | { |
||
240 | idxNum |= 4; |
||
241 | gtIdx = i; |
||
242 | } |
||
243 | if ( ( idxNum & 12 ) == 0 && pConstraint.op == SQLITE_INDEX_CONSTRAINT_LE ) |
||
244 | { |
||
245 | idxNum |= 8; |
||
246 | gtIdx = i; |
||
247 | } |
||
248 | } |
||
249 | pIdxInfo.idxNum = idxNum; |
||
250 | if ( ltIdx >= 0 ) |
||
251 | { |
||
252 | pIdxInfo.aConstraintUsage[ltIdx].argvIndex = argvIdx++; |
||
253 | pIdxInfo.aConstraintUsage[ltIdx].omit = true; |
||
254 | } |
||
255 | if ( gtIdx >= 0 ) |
||
256 | { |
||
257 | pIdxInfo.aConstraintUsage[gtIdx].argvIndex = argvIdx; |
||
258 | pIdxInfo.aConstraintUsage[gtIdx].omit = true; |
||
259 | } |
||
260 | if ( pIdxInfo.nOrderBy == 1 |
||
261 | && pIdxInfo.aOrderBy[0].desc == false |
||
262 | ) |
||
263 | { |
||
264 | pIdxInfo.orderByConsumed = true; |
||
265 | } |
||
266 | pIdxInfo.estimatedCost = (double)1; |
||
267 | return SQLITE_OK; |
||
268 | } |
||
269 | |||
270 | /* |
||
271 | ** A virtual table module that provides read-only access to a |
||
272 | ** Tcl global variable namespace. |
||
273 | */ |
||
274 | static sqlite3_module wholenumberModule = new sqlite3_module( |
||
275 | 2, /* iVersion */ |
||
276 | (smdxCreateConnect)wholenumberConnect, |
||
277 | (smdxCreateConnect)wholenumberConnect, |
||
278 | (smdxBestIndex)wholenumberBestIndex, |
||
279 | (smdxDisconnect)wholenumberDisconnect, |
||
280 | (smdxDestroy)wholenumberDisconnect, |
||
281 | (smdxOpen)wholenumberOpen, /* xOpen - open a cursor */ |
||
282 | (smdxClose)wholenumberClose, /* xClose - close a cursor */ |
||
283 | (smdxFilter)wholenumberFilter, /* xFilter - configure scan constraints */ |
||
284 | (smdxNext)wholenumberNext, /* xNext - advance a cursor */ |
||
285 | (smdxEof)wholenumberEof, /* xEof - check for end of scan */ |
||
286 | (smdxColumn)wholenumberColumn, /* xColumn - read data */ |
||
287 | (smdxRowid)wholenumberRowid, /* xRowid - read data */ |
||
288 | null, /* xUpdate */ |
||
289 | null, /* xBegin */ |
||
290 | null, /* xSync */ |
||
291 | null, /* xCommit */ |
||
292 | null, /* xRollback */ |
||
293 | null, /* xFindMethod */ |
||
294 | null, /* xRename */ |
||
295 | /* The methods above are in version 1 of the sqlite_module object. Those |
||
296 | ** below are for version 2 and greater. */ |
||
297 | null, |
||
298 | null, |
||
299 | null |
||
300 | ); |
||
301 | |||
302 | #endif //* SQLITE_OMIT_VIRTUALTABLE */ |
||
303 | |||
304 | |||
305 | /* |
||
306 | ** Register the wholenumber virtual table |
||
307 | */ |
||
308 | static int wholenumber_register( sqlite3 db ) |
||
309 | { |
||
310 | int rc = SQLITE_OK; |
||
311 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
312 | rc = sqlite3_create_module( db, "wholenumber", wholenumberModule, null ); |
||
313 | #endif |
||
314 | return rc; |
||
315 | } |
||
316 | |||
317 | #if SQLITE_TEST |
||
318 | //#include <tcl.h> |
||
319 | /* |
||
320 | ** Decode a pointer to an sqlite3 object. |
||
321 | */ |
||
322 | //extern int getDbPointer(Tcl_Interp interp, string zA, sqlite3 **ppDb); |
||
323 | |||
324 | /* |
||
325 | ** Register the echo virtual table module. |
||
326 | */ |
||
327 | static int register_wholenumber_module( |
||
328 | ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ |
||
329 | Tcl_Interp interp, /* The TCL interpreter that invoked this command */ |
||
330 | int objc, /* Number of arguments */ |
||
331 | Tcl_Obj[] objv /* Command arguments */ |
||
332 | ) |
||
333 | { |
||
334 | sqlite3 db = null; |
||
335 | if ( objc != 2 ) |
||
336 | { |
||
337 | TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB" ); |
||
338 | return TCL.TCL_ERROR; |
||
339 | } |
||
340 | if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) |
||
341 | return TCL.TCL_ERROR; |
||
342 | wholenumber_register( db ); |
||
343 | return TCL.TCL_OK; |
||
344 | } |
||
345 | |||
346 | |||
347 | //static class _aObjCmd { |
||
348 | // public string zName; |
||
349 | // public Tcl_ObjCmdProc xProc; |
||
350 | // public object clientData; |
||
351 | //} |
||
352 | /* |
||
353 | ** Register commands with the TCL interpreter. |
||
354 | */ |
||
355 | static public int Sqlitetestwholenumber_Init( Tcl_Interp interp ) |
||
356 | { |
||
357 | _aObjCmd[] aObjCmd = new _aObjCmd[] { |
||
358 | new _aObjCmd( "register_wholenumber_module", register_wholenumber_module, 0 ), |
||
359 | }; |
||
360 | int i; |
||
361 | for ( i = 0; i < aObjCmd.Length; i++ ) |
||
362 | {//sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){ |
||
363 | TCL.Tcl_CreateObjCommand( interp, aObjCmd[i].zName, |
||
364 | aObjCmd[i].xProc, aObjCmd[i].clientData, null ); |
||
365 | } |
||
366 | return TCL.TCL_OK; |
||
367 | } |
||
368 | |||
369 | #endif //* SQLITE_TEST */ |
||
370 | } |
||
371 | #endif |
||
372 | } |