|
1 /* |
|
2 ** 2006 June 14 |
|
3 ** |
|
4 ** The author disclaims copyright to this source code. In place of |
|
5 ** a legal notice, here is a blessing: |
|
6 ** |
|
7 ** May you do good and not evil. |
|
8 ** May you find forgiveness for yourself and forgive others. |
|
9 ** May you share freely, never taking more than you give. |
|
10 ** |
|
11 ************************************************************************* |
|
12 ** Test extension for testing the sqlite3_load_extension() function. |
|
13 ** |
|
14 ** $Id: test_loadext.c,v 1.3 2008/08/02 03:50:39 drh Exp $ |
|
15 */ |
|
16 #include <string.h> |
|
17 #include "sqlite3ext.h" |
|
18 SQLITE_EXTENSION_INIT1 |
|
19 |
|
20 /* |
|
21 ** The half() SQL function returns half of its input value. |
|
22 */ |
|
23 static void halfFunc( |
|
24 sqlite3_context *context, |
|
25 int argc, |
|
26 sqlite3_value **argv |
|
27 ){ |
|
28 sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0])); |
|
29 } |
|
30 |
|
31 /* |
|
32 ** SQL functions to call the sqlite3_status function and return results. |
|
33 */ |
|
34 static void statusFunc( |
|
35 sqlite3_context *context, |
|
36 int argc, |
|
37 sqlite3_value **argv |
|
38 ){ |
|
39 int op, mx, cur, resetFlag, rc; |
|
40 if( sqlite3_value_type(argv[0])==SQLITE_INTEGER ){ |
|
41 op = sqlite3_value_int(argv[0]); |
|
42 }else if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){ |
|
43 int i; |
|
44 const char *zName; |
|
45 static const struct { |
|
46 const char *zName; |
|
47 int op; |
|
48 } aOp[] = { |
|
49 { "MEMORY_USED", SQLITE_STATUS_MEMORY_USED }, |
|
50 { "PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED }, |
|
51 { "PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW }, |
|
52 { "SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED }, |
|
53 { "SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW }, |
|
54 { "MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE }, |
|
55 }; |
|
56 int nOp = sizeof(aOp)/sizeof(aOp[0]); |
|
57 zName = (const char*)sqlite3_value_text(argv[0]); |
|
58 for(i=0; i<nOp; i++){ |
|
59 if( strcmp(aOp[i].zName, zName)==0 ){ |
|
60 op = aOp[i].op; |
|
61 break; |
|
62 } |
|
63 } |
|
64 if( i>=nOp ){ |
|
65 char *zMsg = sqlite3_mprintf("unknown status property: %s", zName); |
|
66 sqlite3_result_error(context, zMsg, -1); |
|
67 sqlite3_free(zMsg); |
|
68 return; |
|
69 } |
|
70 }else{ |
|
71 sqlite3_result_error(context, "unknown status type", -1); |
|
72 return; |
|
73 } |
|
74 if( argc==2 ){ |
|
75 resetFlag = sqlite3_value_int(argv[1]); |
|
76 }else{ |
|
77 resetFlag = 0; |
|
78 } |
|
79 rc = sqlite3_status(op, &cur, &mx, resetFlag); |
|
80 if( rc!=SQLITE_OK ){ |
|
81 char *zMsg = sqlite3_mprintf("sqlite3_status(%d,...) returns %d", op, rc); |
|
82 sqlite3_result_error(context, zMsg, -1); |
|
83 sqlite3_free(zMsg); |
|
84 return; |
|
85 } |
|
86 if( argc==2 ){ |
|
87 sqlite3_result_int(context, mx); |
|
88 }else{ |
|
89 sqlite3_result_int(context, cur); |
|
90 } |
|
91 } |
|
92 |
|
93 /* |
|
94 ** Extension load function. |
|
95 */ |
|
96 int testloadext_init( |
|
97 sqlite3 *db, |
|
98 char **pzErrMsg, |
|
99 const sqlite3_api_routines *pApi |
|
100 ){ |
|
101 int nErr = 0; |
|
102 SQLITE_EXTENSION_INIT2(pApi); |
|
103 nErr |= sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0); |
|
104 nErr |= sqlite3_create_function(db, "sqlite3_status", 1, SQLITE_ANY, 0, |
|
105 statusFunc, 0, 0); |
|
106 nErr |= sqlite3_create_function(db, "sqlite3_status", 2, SQLITE_ANY, 0, |
|
107 statusFunc, 0, 0); |
|
108 return nErr ? SQLITE_ERROR : SQLITE_OK; |
|
109 } |
|
110 |
|
111 /* |
|
112 ** Another extension entry point. This one always fails. |
|
113 */ |
|
114 int testbrokenext_init( |
|
115 sqlite3 *db, |
|
116 char **pzErrMsg, |
|
117 const sqlite3_api_routines *pApi |
|
118 ){ |
|
119 char *zErr; |
|
120 SQLITE_EXTENSION_INIT2(pApi); |
|
121 zErr = sqlite3_mprintf("broken!"); |
|
122 *pzErrMsg = zErr; |
|
123 return 1; |
|
124 } |