1 /*
2 ** 2020-01-11
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 **
13 ** This SQLite extension implements various SQL functions used to access
14 ** the following SQLite C-language APIs:
15 **
16 **         sqlite3_uri_parameter()
17 **         sqlite3_uri_boolean()
18 **         sqlite3_uri_int64()
19 **         sqlite3_uri_key()
20 **         sqlite3_filename_database()
21 **         sqlite3_filename_journal()
22 **         sqlite3_filename_wal()
23 **         sqlite3_db_filename()
24 **
25 ** These SQL functions are for testing and demonstration purposes only.
26 **
27 **
28 */
29 #include "sqlite3ext.h"
30 SQLITE_EXTENSION_INIT1
31 #include <assert.h>
32 #include <string.h>
33 
34 /*
35 ** SQL function:    sqlite3_db_filename(SCHEMA)
36 **
37 ** Return the filename corresponding to SCHEMA.
38 */
func_db_filename(sqlite3_context * context,int argc,sqlite3_value ** argv)39 static void func_db_filename(
40   sqlite3_context *context,
41   int argc,
42   sqlite3_value **argv
43 ){
44   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
45   sqlite3 *db = sqlite3_context_db_handle(context);
46   const char *zFile = sqlite3_db_filename(db, zSchema);
47   sqlite3_result_text(context, zFile, -1, SQLITE_TRANSIENT);
48 }
49 
50 /*
51 ** SQL function:    sqlite3_uri_parameter(SCHEMA,NAME)
52 **
53 ** Return the value of the NAME query parameter to the database for SCHEMA
54 */
func_uri_parameter(sqlite3_context * context,int argc,sqlite3_value ** argv)55 static void func_uri_parameter(
56   sqlite3_context *context,
57   int argc,
58   sqlite3_value **argv
59 ){
60   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
61   sqlite3 *db = sqlite3_context_db_handle(context);
62   const char *zName = (const char*)sqlite3_value_text(argv[1]);
63   const char *zFile = sqlite3_db_filename(db, zSchema);
64   const char *zRes = sqlite3_uri_parameter(zFile, zName);
65   sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
66 }
67 
68 /*
69 ** SQL function:    sqlite3_uri_boolean(SCHEMA,NAME,DEFAULT)
70 **
71 ** Return the boolean value of the NAME query parameter to
72 ** the database for SCHEMA
73 */
func_uri_boolean(sqlite3_context * context,int argc,sqlite3_value ** argv)74 static void func_uri_boolean(
75   sqlite3_context *context,
76   int argc,
77   sqlite3_value **argv
78 ){
79   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
80   sqlite3 *db = sqlite3_context_db_handle(context);
81   const char *zName = (const char*)sqlite3_value_text(argv[1]);
82   const char *zFile = sqlite3_db_filename(db, zSchema);
83   int iDflt = sqlite3_value_int(argv[2]);
84   int iRes = sqlite3_uri_boolean(zFile, zName, iDflt);
85   sqlite3_result_int(context, iRes);
86 }
87 
88 /*
89 ** SQL function:    sqlite3_uri_key(SCHEMA,N)
90 **
91 ** Return the name of the Nth query parameter
92 */
func_uri_key(sqlite3_context * context,int argc,sqlite3_value ** argv)93 static void func_uri_key(
94   sqlite3_context *context,
95   int argc,
96   sqlite3_value **argv
97 ){
98   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
99   sqlite3 *db = sqlite3_context_db_handle(context);
100   int N = sqlite3_value_int(argv[1]);
101   const char *zFile = sqlite3_db_filename(db, zSchema);
102   const char *zRes = sqlite3_uri_key(zFile, N);
103   sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
104 }
105 
106 /*
107 ** SQL function:    sqlite3_uri_int64(SCHEMA,NAME,DEFAULT)
108 **
109 ** Return the int64 value of the NAME query parameter to
110 ** the database for SCHEMA
111 */
func_uri_int64(sqlite3_context * context,int argc,sqlite3_value ** argv)112 static void func_uri_int64(
113   sqlite3_context *context,
114   int argc,
115   sqlite3_value **argv
116 ){
117   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
118   sqlite3 *db = sqlite3_context_db_handle(context);
119   const char *zName = (const char*)sqlite3_value_text(argv[1]);
120   const char *zFile = sqlite3_db_filename(db, zSchema);
121   sqlite3_int64 iDflt = sqlite3_value_int64(argv[2]);
122   sqlite3_int64 iRes = sqlite3_uri_int64(zFile, zName, iDflt);
123   sqlite3_result_int64(context, iRes);
124 }
125 
126 /*
127 ** SQL function:    sqlite3_filename_database(SCHEMA)
128 **
129 ** Return the database filename for SCHEMA
130 */
func_filename_database(sqlite3_context * context,int argc,sqlite3_value ** argv)131 static void func_filename_database(
132   sqlite3_context *context,
133   int argc,
134   sqlite3_value **argv
135 ){
136   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
137   sqlite3 *db = sqlite3_context_db_handle(context);
138   const char *zFile = sqlite3_db_filename(db, zSchema);
139   const char *zRes = zFile ? sqlite3_filename_database(zFile) : 0;
140   sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
141 }
142 
143 /*
144 ** SQL function:    sqlite3_filename_journal(SCHEMA)
145 **
146 ** Return the rollback journal filename for SCHEMA
147 */
func_filename_journal(sqlite3_context * context,int argc,sqlite3_value ** argv)148 static void func_filename_journal(
149   sqlite3_context *context,
150   int argc,
151   sqlite3_value **argv
152 ){
153   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
154   sqlite3 *db = sqlite3_context_db_handle(context);
155   const char *zFile = sqlite3_db_filename(db, zSchema);
156   const char *zRes = zFile ? sqlite3_filename_journal(zFile) : 0;
157   sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
158 }
159 
160 /*
161 ** SQL function:    sqlite3_filename_wal(SCHEMA)
162 **
163 ** Return the WAL filename for SCHEMA
164 */
func_filename_wal(sqlite3_context * context,int argc,sqlite3_value ** argv)165 static void func_filename_wal(
166   sqlite3_context *context,
167   int argc,
168   sqlite3_value **argv
169 ){
170   const char *zSchema = (const char*)sqlite3_value_text(argv[0]);
171   sqlite3 *db = sqlite3_context_db_handle(context);
172   const char *zFile = sqlite3_db_filename(db, zSchema);
173   const char *zRes = zFile ? sqlite3_filename_wal(zFile) : 0;
174   sqlite3_result_text(context, zRes, -1, SQLITE_TRANSIENT);
175 }
176 
177 #ifdef _WIN32
178 __declspec(dllexport)
179 #endif
sqlite3_urifuncs_init(sqlite3 * db,char ** pzErrMsg,const sqlite3_api_routines * pApi)180 int sqlite3_urifuncs_init(
181   sqlite3 *db,
182   char **pzErrMsg,
183   const sqlite3_api_routines *pApi
184 ){
185   static const struct {
186     const char *zFuncName;
187     int nArg;
188     void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
189   } aFunc[] = {
190     { "sqlite3_db_filename",       1, func_db_filename       },
191     { "sqlite3_uri_parameter",     2, func_uri_parameter     },
192     { "sqlite3_uri_boolean",       3, func_uri_boolean       },
193     { "sqlite3_uri_int64",         3, func_uri_int64         },
194     { "sqlite3_uri_key",           2, func_uri_key           },
195     { "sqlite3_filename_database", 1, func_filename_database },
196     { "sqlite3_filename_journal",  1, func_filename_journal  },
197     { "sqlite3_filename_wal",      1, func_filename_wal      },
198   };
199   int rc = SQLITE_OK;
200   int i;
201   SQLITE_EXTENSION_INIT2(pApi);
202   (void)pzErrMsg;  /* Unused parameter */
203   for(i=0; rc==SQLITE_OK && i<sizeof(aFunc)/sizeof(aFunc[0]); i++){
204     rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
205                      SQLITE_UTF8, 0,
206                      aFunc[i].xFunc, 0, 0);
207   }
208   return rc;
209 }
210