blob: 8acbb9bf5fd12d7e6f2392a1e019ac90d1d96144 [file] [log] [blame]
drh5fa5c102015-08-12 16:49:40 +00001/*
2** 2015-08-12
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 JSON functions. The interface is
14** modeled after MySQL JSON functions:
15**
16** https://dev.mysql.com/doc/refman/5.7/en/json.html
17**
18** JSON is pure text. JSONB is a binary encoding that is smaller and easier
19** to parse but which holds the equivalent information. Conversions between
20** JSON and JSONB are lossless.
21**
22** Most of the functions here will accept either JSON or JSONB input. The
23** input is understood to be JSONB if it a BLOB and JSON if the input is
24** of any other type. Functions that begin with the "json_" prefix return
25** JSON and functions that begin with "jsonb_" return JSONB.
26*/
27#include "sqlite3ext.h"
28SQLITE_EXTENSION_INIT1
29#include <assert.h>
30#include <string.h>
31
32/* Unsigned integer types */
33typedef sqlite3_uint64 u64;
34typedef unsigned int u32;
35typedef unsigned char u8;
36
37/* An instance of this object represents a JSON string under construction.
38*/
39typedef struct Json Json;
40struct Json {
41 sqlite3_context *pCtx; /* Function context - put error messages here */
42 char *zBuf; /* Append JSON text here */
43 u64 nAlloc; /* Bytes of storage available in zBuf[] */
44 u64 nUsed; /* Bytes of zBuf[] currently used */
45 u8 bStatic; /* True if zBuf is static space */
46 u8 mallocFailed; /* True if an OOM has been encountered */
47 char zSpace[100]; /* Initial static space */
48};
49
50/* Set the Json object to an empty string
51*/
52static void jsonZero(Json *p){
53 p->zBuf = p->zSpace;
54 p->nAlloc = sizeof(p->zSpace);
55 p->nUsed = 0;
56 p->bStatic = 1;
57}
58
59/* Initialize the Json object
60*/
61static void jsonInit(Json *p, sqlite3_context *pCtx){
62 p->pCtx = pCtx;
63 p->mallocFailed = 0;
64 jsonZero(p);
65}
66
67
68/* Free all allocated memory and reset the Json object back to its
69** initial state.
70*/
71static void jsonReset(Json *p){
72 if( !p->bStatic ) sqlite3_free(p->zBuf);
73 jsonZero(p);
74}
75
76
77/* Report an out-of-memory (OOM) condition
78*/
79static void jsonOom(Json *p){
80 p->mallocFailed = 1;
81 sqlite3_result_error_nomem(p->pCtx);
82 jsonReset(p);
83}
84
85/* Enlarge pJson->zBuf so that it can hold at least N more bytes.
86** Return zero on success. Return non-zero on an OOM error
87*/
88static int jsonGrow(Json *p, u32 N){
89 u64 nTotal = N<p->nAlloc ? p->nAlloc*2 : p->nAlloc+N+100;
90 char *zNew;
91 if( p->bStatic ){
92 if( p->mallocFailed ) return SQLITE_NOMEM;
93 zNew = sqlite3_malloc64(nTotal);
94 if( zNew==0 ){
95 jsonOom(p);
96 return SQLITE_NOMEM;
97 }
98 memcpy(zNew, p->zBuf, p->nUsed);
99 p->zBuf = zNew;
100 p->bStatic = 0;
101 }else{
102 zNew = sqlite3_realloc64(p->zBuf, nTotal);
103 if( zNew==0 ){
104 jsonOom(p);
105 return SQLITE_NOMEM;
106 }
107 p->zBuf = zNew;
108 }
109 p->nAlloc = nTotal;
110 return SQLITE_OK;
111}
112
113/* Append N bytes from zIn onto the end of the Json string.
114*/
115static void jsonAppendRaw(Json *p, const char *zIn, u32 N){
116 if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
117 memcpy(p->zBuf+p->nUsed, zIn, N);
118 p->nUsed += N;
119}
120
121/* Append the N-byte string in zIn to the end of the Json string
122** under construction. Enclose the string in "..." and escape
123** any double-quotes or backslash characters contained within the
124** string.
125*/
126static void jsonAppendString(Json *p, const char *zIn, u32 N){
127 u32 i;
128 if( (N+p->nUsed+2 >= p->nAlloc) && jsonGrow(p,N+2)!=0 ) return;
129 p->zBuf[p->nUsed++] = '"';
130 for(i=0; i<N; i++){
131 char c = zIn[i];
132 if( c=='"' || c=='\\' ){
133 if( (p->nUsed+N+1-i > p->nAlloc) && jsonGrow(p,N+1-i)!=0 ) return;
134 p->zBuf[p->nUsed++] = '\\';
135 }
136 p->zBuf[p->nUsed++] = c;
137 }
138 p->zBuf[p->nUsed++] = '"';
139}
140
141/* Make pJson the result of the SQL function.
142*/
143static void jsonResult(Json *p){
144 if( p->mallocFailed==0 ){
145 sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
146 p->bStatic ? SQLITE_TRANSIENT : sqlite3_free,
147 SQLITE_UTF8);
148 jsonZero(p);
149 }
150 assert( p->bStatic );
151}
152
153/*
154** Implementation of the json_array(VALUE,...) function. Return a JSON
155** array that contains all values given in arguments. Or if any argument
156** is a BLOB, throw an error.
157*/
158static void jsonArrayFunc(
159 sqlite3_context *context,
160 int argc,
161 sqlite3_value **argv
162){
163 int i;
164 Json jx;
165 char cSep = '[';
166
167 jsonInit(&jx, context);
168 for(i=0; i<argc; i++){
169 jsonAppendRaw(&jx, &cSep, 1);
170 cSep = ',';
171 switch( sqlite3_value_type(argv[i]) ){
172 case SQLITE_NULL: {
173 jsonAppendRaw(&jx, "null", 4);
174 break;
175 }
176 case SQLITE_INTEGER:
177 case SQLITE_FLOAT: {
178 const char *z = (const char*)sqlite3_value_text(argv[i]);
179 u32 n = (u32)sqlite3_value_bytes(argv[i]);
180 jsonAppendRaw(&jx, z, n);
181 break;
182 }
183 case SQLITE_TEXT: {
184 const char *z = (const char*)sqlite3_value_text(argv[i]);
185 u32 n = (u32)sqlite3_value_bytes(argv[i]);
186 jsonAppendString(&jx, z, n);
187 break;
188 }
189 default: {
190 jsonZero(&jx);
191 sqlite3_result_error(context, "JSON cannot hold BLOB values", -1);
192 return;
193 }
194 }
195 }
196 jsonAppendRaw(&jx, "]", 1);
drh2032d602015-08-12 17:23:34 +0000197 jsonResult(&jx);
198}
199
200/*
201** Implementation of the json_object(NAME,VALUE,...) function. Return a JSON
202** object that contains all name/value given in arguments. Or if any name
203** is not a string or if any value is a BLOB, throw an error.
204*/
205static void jsonObjectFunc(
206 sqlite3_context *context,
207 int argc,
208 sqlite3_value **argv
209){
210 int i;
211 Json jx;
212 char cSep = '{';
213 const char *z;
214 u32 n;
215
216 if( argc&1 ){
217 sqlite3_result_error(context, "json_object() requires an even number "
218 "of arguments", -1);
219 return;
220 }
221 jsonInit(&jx, context);
222 for(i=0; i<argc; i+=2){
223 jsonAppendRaw(&jx, &cSep, 1);
224 cSep = ',';
225 if( sqlite3_value_type(argv[i])!=SQLITE_TEXT ){
226 sqlite3_result_error(context, "json_object() labels must be TEXT", -1);
227 jsonZero(&jx);
228 return;
229 }
230 z = (const char*)sqlite3_value_text(argv[i]);
231 n = (u32)sqlite3_value_bytes(argv[i]);
232 jsonAppendString(&jx, z, n);
233 jsonAppendRaw(&jx, ":", 1);
234 switch( sqlite3_value_type(argv[i+1]) ){
235 case SQLITE_NULL: {
236 jsonAppendRaw(&jx, "null", 4);
237 break;
238 }
239 case SQLITE_INTEGER:
240 case SQLITE_FLOAT: {
241 z = (const char*)sqlite3_value_text(argv[i+1]);
242 n = (u32)sqlite3_value_bytes(argv[i+1]);
243 jsonAppendRaw(&jx, z, n);
244 break;
245 }
246 case SQLITE_TEXT: {
247 z = (const char*)sqlite3_value_text(argv[i+1]);
248 n = (u32)sqlite3_value_bytes(argv[i+1]);
249 jsonAppendString(&jx, z, n);
250 break;
251 }
252 default: {
253 jsonZero(&jx);
254 sqlite3_result_error(context, "JSON cannot hold BLOB values", -1);
255 return;
256 }
257 }
258 }
259 jsonAppendRaw(&jx, "}", 1);
260 jsonResult(&jx);
drh5fa5c102015-08-12 16:49:40 +0000261}
262
263#ifdef _WIN32
264__declspec(dllexport)
265#endif
266int sqlite3_json_init(
267 sqlite3 *db,
268 char **pzErrMsg,
269 const sqlite3_api_routines *pApi
270){
271 int rc = SQLITE_OK;
272 int i;
273 static const struct {
274 const char *zName;
275 int nArg;
276 void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
277 } aFunc[] = {
drh2032d602015-08-12 17:23:34 +0000278 { "json_array", -1, jsonArrayFunc },
279 { "json_object", -1, jsonObjectFunc },
drh5fa5c102015-08-12 16:49:40 +0000280 };
281 SQLITE_EXTENSION_INIT2(pApi);
282 (void)pzErrMsg; /* Unused parameter */
283 for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
284 rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
285 SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
286 aFunc[i].xFunc, 0, 0);
287 }
288 return rc;
289}