wasCSharpSQLite – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System.Diagnostics; |
2 | |||
3 | using u8 = System.Byte; |
||
4 | using u32 = System.UInt32; |
||
5 | |||
6 | namespace Community.CsharpSqlite |
||
7 | { |
||
8 | #if TCLSH |
||
9 | using tcl.lang; |
||
10 | using DbPage = Sqlite3.PgHdr; |
||
11 | using sqlite_int64 = System.Int64; |
||
12 | using sqlite3_int64 = System.Int64; |
||
13 | using sqlite3_stmt = Sqlite3.Vdbe; |
||
14 | using sqlite3_value = Sqlite3.Mem; |
||
15 | using Tcl_CmdInfo = tcl.lang.WrappedCommand; |
||
16 | using Tcl_Interp = tcl.lang.Interp; |
||
17 | using Tcl_Obj = tcl.lang.TclObject; |
||
18 | using ClientData = System.Object; |
||
19 | using System; |
||
20 | using System.Text; |
||
21 | #endif |
||
22 | |||
23 | public partial class Sqlite3 |
||
24 | { |
||
25 | /* |
||
26 | ** 2009 November 10 |
||
27 | ** |
||
28 | ** The author disclaims copyright to this source code. In place of |
||
29 | ** a legal notice, here is a blessing: |
||
30 | ** |
||
31 | ** May you do good and not evil. |
||
32 | ** May you find forgiveness for yourself and forgive others. |
||
33 | ** May you share freely, never taking more than you give. |
||
34 | ** |
||
35 | ************************************************************************* |
||
36 | ** |
||
37 | ** This file implements a read-only VIRTUAL TABLE that contains the |
||
38 | ** content of a C-language array of integer values. See the corresponding |
||
39 | ** header file for full details. |
||
40 | ************************************************************************* |
||
41 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
42 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
43 | ** |
||
44 | ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 |
||
45 | ** |
||
46 | ************************************************************************* |
||
47 | */ |
||
48 | //#include "test_intarray.h" |
||
49 | //#include <string.h> |
||
50 | //#include <Debug.Assert.h> |
||
51 | |||
52 | |||
53 | /* |
||
54 | ** Definition of the sqlite3_intarray object. |
||
55 | ** |
||
56 | ** The internal representation of an intarray object is subject |
||
57 | ** to change, is not externally visible, and should be used by |
||
58 | ** the implementation of intarray only. This object is opaque |
||
59 | ** to users. |
||
60 | */ |
||
61 | class sqlite3_intarray : sqlite3_vtab |
||
62 | { |
||
63 | public int n; /* Number of elements in the array */ |
||
64 | public sqlite3_int64[] a; /* Contents of the array */ |
||
65 | public dxFree xFree;//void (*xFree)(void*); /* Function used to free a[] */ |
||
66 | }; |
||
67 | |||
68 | /* Objects used internally by the virtual table implementation */ |
||
69 | //typedef struct intarray_vtab intarray_vtab; |
||
70 | //typedef struct intarray_cursor intarray_cursor; |
||
71 | |||
72 | /* A intarray table object */ |
||
73 | class intarray_vtab : sqlite3_vtab |
||
74 | { |
||
75 | //sqlite3_vtab base; /* Base class */ |
||
76 | public sqlite3_intarray pContent; /* Content of the integer array */ |
||
77 | }; |
||
78 | |||
79 | /* A intarray cursor object */ |
||
80 | class intarray_cursor : sqlite3_vtab_cursor |
||
81 | { |
||
82 | //sqlite3_vtab_cursor base; /* Base class */ |
||
83 | public int i; /* Current cursor position */ |
||
84 | }; |
||
85 | |||
86 | /* |
||
87 | ** None of this works unless we have virtual tables. |
||
88 | */ |
||
89 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
90 | |||
91 | /* |
||
92 | ** Free an sqlite3_intarray object. |
||
93 | */ |
||
94 | static int intarrayFree( ref object p ) |
||
95 | { |
||
96 | //if ( ( (sqlite3_intarray)p ).xFree != null ) |
||
97 | //{ |
||
98 | // p.xFree( ref p.a ); |
||
99 | //} |
||
100 | p = null;//sqlite3_free(p); |
||
101 | return 0; |
||
102 | } |
||
103 | |||
104 | /* |
||
105 | ** Table destructor for the intarray module. |
||
106 | */ |
||
107 | static int intarrayDestroy( ref object p ) |
||
108 | { |
||
109 | //intarray_vtab *pVtab = (intarray_vtab*)p; |
||
110 | //sqlite3_free(pVtab); |
||
111 | p = null; |
||
112 | return 0; |
||
113 | } |
||
114 | |||
115 | /* |
||
116 | ** Table constructor for the intarray module. |
||
117 | */ |
||
118 | static int intarrayCreate( |
||
119 | sqlite3 db, /* Database where module is created */ |
||
120 | object pAux, /* clientdata for the module */ |
||
121 | int argc, /* Number of arguments */ |
||
122 | string[] argv, /* Value for all arguments */ |
||
123 | out sqlite3_vtab ppVtab, /* Write the new virtual table object here */ |
||
124 | out string pzErr /* Put error message text here */ |
||
125 | ) |
||
126 | { |
||
127 | int rc = SQLITE_NOMEM; |
||
128 | intarray_vtab pVtab = new intarray_vtab();//sqlite3_malloc(sizeof(intarray_vtab)); |
||
129 | |||
130 | if ( pVtab != null ) |
||
131 | { |
||
132 | //memset(pVtab, 0, sizeof(intarray_vtab)); |
||
133 | pVtab.pContent = (sqlite3_intarray)pAux; |
||
134 | rc = sqlite3_declare_vtab( db, "CREATE TABLE x(value INTEGER PRIMARY KEY)" ); |
||
135 | } |
||
136 | ppVtab = (sqlite3_vtab)pVtab; |
||
137 | pzErr = ""; |
||
138 | return rc; |
||
139 | } |
||
140 | |||
141 | /* |
||
142 | ** Open a new cursor on the intarray table. |
||
143 | */ |
||
144 | static int intarrayOpen( sqlite3_vtab pVTab, out sqlite3_vtab_cursor ppCursor ) |
||
145 | { |
||
146 | int rc = SQLITE_NOMEM; |
||
147 | intarray_cursor pCur = new intarray_cursor();// |
||
148 | //pCur = sqlite3_malloc(sizeof(intarray_cursor)); |
||
149 | //if ( pCur != null ) |
||
150 | { |
||
151 | //memset(pCur, 0, sizeof(intarray_cursor)); |
||
152 | ppCursor = (sqlite3_vtab_cursor)pCur; |
||
153 | rc = SQLITE_OK; |
||
154 | } |
||
155 | return rc; |
||
156 | } |
||
157 | |||
158 | /* |
||
159 | ** Close a intarray table cursor. |
||
160 | */ |
||
161 | static int intarrayClose( ref sqlite3_vtab_cursor cur ) |
||
162 | { |
||
163 | //intarray_cursor *pCur = (intarray_cursor *)cur; |
||
164 | //sqlite3_free(pCur); |
||
165 | cur = null; |
||
166 | return SQLITE_OK; |
||
167 | } |
||
168 | |||
169 | /* |
||
170 | ** Retrieve a column of data. |
||
171 | */ |
||
172 | static int intarrayColumn( sqlite3_vtab_cursor cur, sqlite3_context ctx, int i ) |
||
173 | { |
||
174 | intarray_cursor pCur = (intarray_cursor)cur; |
||
175 | intarray_vtab pVtab = (intarray_vtab)cur.pVtab; |
||
176 | if ( pCur.i >= 0 && pCur.i < pVtab.pContent.n ) |
||
177 | { |
||
178 | sqlite3_result_int64( ctx, pVtab.pContent.a[pCur.i] ); |
||
179 | } |
||
180 | return SQLITE_OK; |
||
181 | } |
||
182 | |||
183 | /* |
||
184 | ** Retrieve the current rowid. |
||
185 | */ |
||
186 | static int intarrayRowid( sqlite3_vtab_cursor cur, out sqlite_int64 pRowid ) |
||
187 | { |
||
188 | intarray_cursor pCur = (intarray_cursor)cur; |
||
189 | pRowid = pCur.i; |
||
190 | return SQLITE_OK; |
||
191 | } |
||
192 | |||
193 | static int intarrayEof( sqlite3_vtab_cursor cur ) |
||
194 | { |
||
195 | intarray_cursor pCur = (intarray_cursor)cur; |
||
196 | intarray_vtab pVtab = (intarray_vtab)cur.pVtab; |
||
197 | return pCur.i >= pVtab.pContent.n ? 1 : 0; |
||
198 | } |
||
199 | |||
200 | /* |
||
201 | ** Advance the cursor to the next row. |
||
202 | */ |
||
203 | static int intarrayNext( sqlite3_vtab_cursor cur ) |
||
204 | { |
||
205 | intarray_cursor pCur = (intarray_cursor)cur; |
||
206 | pCur.i++; |
||
207 | return SQLITE_OK; |
||
208 | } |
||
209 | |||
210 | /* |
||
211 | ** Reset a intarray table cursor. |
||
212 | */ |
||
213 | static int intarrayFilter( |
||
214 | sqlite3_vtab_cursor pVtabCursor, |
||
215 | int idxNum, string idxStr, |
||
216 | int argc, sqlite3_value[] argv |
||
217 | ) |
||
218 | { |
||
219 | intarray_cursor pCur = (intarray_cursor)pVtabCursor; |
||
220 | pCur.i = 0; |
||
221 | return SQLITE_OK; |
||
222 | } |
||
223 | |||
224 | /* |
||
225 | ** Analyse the WHERE condition. |
||
226 | */ |
||
227 | static int intarrayBestIndex( sqlite3_vtab tab, ref sqlite3_index_info pIdxInfo ) |
||
228 | { |
||
229 | return SQLITE_OK; |
||
230 | } |
||
231 | |||
232 | /* |
||
233 | ** A virtual table module that merely echos method calls into TCL |
||
234 | ** variables. |
||
235 | */ |
||
236 | static sqlite3_module intarrayModule = new sqlite3_module( |
||
237 | 0, /* iVersion */ |
||
238 | intarrayCreate, /* xCreate - create a new virtual table */ |
||
239 | intarrayCreate, /* xConnect - connect to an existing vtab */ |
||
240 | intarrayBestIndex, /* xBestIndex - find the best query index */ |
||
241 | intarrayDestroy, /* xDisconnect - disconnect a vtab */ |
||
242 | intarrayDestroy, /* xDestroy - destroy a vtab */ |
||
243 | intarrayOpen, /* xOpen - open a cursor */ |
||
244 | intarrayClose, /* xClose - close a cursor */ |
||
245 | intarrayFilter, /* xFilter - configure scan constraints */ |
||
246 | intarrayNext, /* xNext - advance a cursor */ |
||
247 | intarrayEof, /* xEof */ |
||
248 | intarrayColumn, /* xColumn - read data */ |
||
249 | intarrayRowid, /* xRowid - read data */ |
||
250 | null, /* xUpdate */ |
||
251 | null, /* xBegin */ |
||
252 | null, /* xSync */ |
||
253 | null, /* xCommit */ |
||
254 | null, /* xRollback */ |
||
255 | null, /* xFindMethod */ |
||
256 | null /* xRename */ |
||
257 | ); |
||
258 | |||
259 | #endif //* !defined(SQLITE_OMIT_VIRTUALTABLE) */ |
||
260 | |||
261 | /* |
||
262 | ** Invoke this routine to create a specific instance of an intarray object. |
||
263 | ** The new intarray object is returned by the 3rd parameter. |
||
264 | ** |
||
265 | ** Each intarray object corresponds to a virtual table in the TEMP table |
||
266 | ** with a name of zName. |
||
267 | ** |
||
268 | ** Destroy the intarray object by dropping the virtual table. If not done |
||
269 | ** explicitly by the application, the virtual table will be dropped implicitly |
||
270 | ** by the system when the database connection is closed. |
||
271 | */ |
||
272 | static int sqlite3_intarray_create( |
||
273 | sqlite3 db, |
||
274 | string zName, |
||
275 | out sqlite3_intarray ppReturn |
||
276 | ) |
||
277 | { |
||
278 | int rc = SQLITE_OK; |
||
279 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
280 | sqlite3_intarray p; |
||
281 | |||
282 | ppReturn = p = new sqlite3_intarray();//sqlite3_malloc( sizeof(*p) ); |
||
283 | //if( p==0 ){ |
||
284 | // return SQLITE_NOMEM; |
||
285 | //} |
||
286 | //memset(p, 0, sizeof(*p)); |
||
287 | rc = sqlite3_create_module_v2( db, zName, intarrayModule, p, |
||
288 | intarrayFree ); |
||
289 | if ( rc == SQLITE_OK ) |
||
290 | { |
||
291 | string zSql; |
||
292 | zSql = sqlite3_mprintf( "CREATE VIRTUAL TABLE temp.%Q USING %Q", |
||
293 | zName, zName ); |
||
294 | rc = sqlite3_exec( db, zSql, 0, 0, 0 ); |
||
295 | //sqlite3_free(zSql); |
||
296 | } |
||
297 | #endif |
||
298 | return rc; |
||
299 | } |
||
300 | |||
301 | /* |
||
302 | ** Bind a new array array of integers to a specific intarray object. |
||
303 | ** |
||
304 | ** The array of integers bound must be unchanged for the duration of |
||
305 | ** any query against the corresponding virtual table. If the integer |
||
306 | ** array does change or is deallocated undefined behavior will result. |
||
307 | */ |
||
308 | static int sqlite3_intarray_bind( |
||
309 | sqlite3_intarray pIntArray, /* The intarray object to bind to */ |
||
310 | int nElements, /* Number of elements in the intarray */ |
||
311 | sqlite3_int64[] aElements, /* Content of the intarray */ |
||
312 | dxFree xFree//void (*xFree)(void*) /* How to dispose of the intarray when done */ |
||
313 | ) |
||
314 | { |
||
315 | if ( pIntArray.xFree != null ) |
||
316 | { |
||
317 | pIntArray.a = null;//pIntArray.xFree( pIntArray.a ); |
||
318 | } |
||
319 | pIntArray.n = nElements; |
||
320 | pIntArray.a = aElements; |
||
321 | pIntArray.xFree = xFree; |
||
322 | return SQLITE_OK; |
||
323 | } |
||
324 | |||
325 | |||
326 | /***************************************************************************** |
||
327 | ** Everything below is interface for testing this module. |
||
328 | */ |
||
329 | #if SQLITE_TEST |
||
330 | //#include <tcl.h> |
||
331 | |||
332 | /* |
||
333 | ** Routines to encode and decode pointers |
||
334 | */ |
||
335 | //extern int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb); |
||
336 | //extern void *sqlite3TestTextToPtr(const char*); |
||
337 | //extern int sqlite3TestMakePointerStr(Tcl_Interp*, char *zPtr, void*); |
||
338 | //extern const char *sqlite3TestErrorName(int); |
||
339 | |||
340 | /* |
||
341 | ** sqlite3_intarray_create DB NAME |
||
342 | ** |
||
343 | ** Invoke the sqlite3_intarray_create interface. A string that becomes |
||
344 | ** the first parameter to sqlite3_intarray_bind. |
||
345 | */ |
||
346 | static int test_intarray_create( |
||
347 | ClientData clientData, /* Not used */ |
||
348 | Tcl_Interp interp, /* The TCL interpreter that invoked this command */ |
||
349 | int objc, /* Number of arguments */ |
||
350 | Tcl_Obj[] objv /* Command arguments */ |
||
351 | ) |
||
352 | { |
||
353 | sqlite3 db; |
||
354 | string zName; |
||
355 | sqlite3_intarray pArray; |
||
356 | int rc = SQLITE_OK; |
||
357 | StringBuilder zPtr = new StringBuilder( 100 ); |
||
358 | |||
359 | if ( objc != 3 ) |
||
360 | { |
||
361 | TCL.Tcl_WrongNumArgs( interp, 1, objv, "DB" ); |
||
362 | return TCL.TCL_ERROR; |
||
363 | } |
||
364 | if ( getDbPointer( interp, TCL.Tcl_GetString( objv[1] ), out db ) != 0 ) |
||
365 | return TCL.TCL_ERROR; |
||
366 | zName = TCL.Tcl_GetString( objv[2] ); |
||
367 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
368 | rc = sqlite3_intarray_create( db, zName, out pArray ); |
||
369 | #endif |
||
370 | if ( rc != SQLITE_OK ) |
||
371 | { |
||
372 | Debug.Assert( pArray == null ); |
||
373 | TCL.Tcl_AppendResult( interp, sqlite3TestErrorName( rc ), null ); |
||
374 | return TCL.TCL_ERROR; |
||
375 | } |
||
376 | sqlite3TestMakePointerStr( interp, zPtr, pArray ); |
||
377 | TCL.Tcl_AppendResult( interp, zPtr, null ); |
||
378 | return TCL.TCL_OK; |
||
379 | } |
||
380 | |||
381 | /* |
||
382 | ** sqlite3_intarray_bind INTARRAY ?VALUE ...? |
||
383 | ** |
||
384 | ** Invoke the sqlite3_intarray_bind interface on the given array of integers. |
||
385 | */ |
||
386 | static int test_intarray_bind( |
||
387 | ClientData clientData, /* Not used */ |
||
388 | Tcl_Interp interp, /* The TCL interpreter that invoked this command */ |
||
389 | int objc, /* Number of arguments */ |
||
390 | Tcl_Obj[] objv /* Command arguments */ |
||
391 | ) |
||
392 | { |
||
393 | sqlite3_intarray pArray; |
||
394 | int rc = SQLITE_OK; |
||
395 | int i, n; |
||
396 | sqlite3_int64[] a; |
||
397 | |||
398 | if ( objc < 2 ) |
||
399 | { |
||
400 | TCL.Tcl_WrongNumArgs( interp, 1, objv, "INTARRAY" ); |
||
401 | return TCL.TCL_ERROR; |
||
402 | } |
||
403 | pArray = (sqlite3_intarray)sqlite3TestTextToPtr( interp, TCL.Tcl_GetString( objv[1] ) ); |
||
404 | n = objc - 2; |
||
405 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
406 | a = new sqlite3_int64[n];//sqlite3_malloc( sizeof(a[0])*n ); |
||
407 | //if( a==0 ){ |
||
408 | // Tcl_AppendResult(interp, "SQLITE_NOMEM", (char*)0); |
||
409 | // return TCL_ERROR; |
||
410 | //} |
||
411 | for ( i = 0; i < n; i++ ) |
||
412 | { |
||
413 | //a[i] = 0; |
||
414 | TCL.Tcl_GetWideIntFromObj( null, objv[i + 2], out a[i] ); |
||
415 | } |
||
416 | rc = sqlite3_intarray_bind( pArray, n, a, sqlite3_free ); |
||
417 | if ( rc != SQLITE_OK ) |
||
418 | { |
||
419 | TCL.Tcl_AppendResult( interp, sqlite3TestErrorName( rc ), null ); |
||
420 | return TCL.TCL_ERROR; |
||
421 | } |
||
422 | #endif |
||
423 | return TCL.TCL_OK; |
||
424 | } |
||
425 | |||
426 | /* |
||
427 | ** Register commands with the TCL interpreter. |
||
428 | */ |
||
429 | static public int Sqlitetestintarray_Init( Tcl_Interp interp ) |
||
430 | { |
||
431 | //static struct { |
||
432 | // char *zName; |
||
433 | // Tcl_ObjCmdProc *xProc; |
||
434 | // void *clientData; |
||
435 | //} |
||
436 | _aObjCmd[] aObjCmd = new _aObjCmd[] { |
||
437 | new _aObjCmd( "sqlite3_intarray_create", test_intarray_create, 0 ), |
||
438 | new _aObjCmd( "sqlite3_intarray_bind", test_intarray_bind, 0 ), |
||
439 | }; |
||
440 | int i; |
||
441 | for ( i = 0; i < aObjCmd.Length; i++ )//sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++) |
||
442 | { |
||
443 | TCL.Tcl_CreateObjCommand( interp, aObjCmd[i].zName, |
||
444 | aObjCmd[i].xProc, aObjCmd[i].clientData, null ); |
||
445 | } |
||
446 | return TCL.TCL_OK; |
||
447 | } |
||
448 | |||
449 | #endif //* SQLITE_TEST */ |
||
450 | } |
||
451 | } |