summaryrefslogtreecommitdiffstats
path: root/common/unqlite/unqlite_jx9.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/unqlite/unqlite_jx9.c')
-rw-r--r--common/unqlite/unqlite_jx9.c977
1 files changed, 977 insertions, 0 deletions
diff --git a/common/unqlite/unqlite_jx9.c b/common/unqlite/unqlite_jx9.c
new file mode 100644
index 0000000..7362c58
--- /dev/null
+++ b/common/unqlite/unqlite_jx9.c
@@ -0,0 +1,977 @@
1/*
2 * Symisc unQLite: An Embeddable NoSQL (Post Modern) Database Engine.
3 * Copyright (C) 2012-2013, Symisc Systems http://unqlite.org/
4 * Version 1.1.6
5 * For information on licensing, redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES
6 * please contact Symisc Systems via:
7 * legal@symisc.net
8 * licensing@symisc.net
9 * contact@symisc.net
10 * or visit:
11 * http://unqlite.org/licensing.html
12 */
13 /* $SymiscID: unql_jx9.c v1.2 FreeBSD 2013-01-24 22:45 stable <chm@symisc.net> $ */
14#ifndef UNQLITE_AMALGAMATION
15#include "unqliteInt.h"
16#endif
17/*
18 * This file implements UnQLite functions (db_exists(), db_create(), db_put(), db_get(), etc.) for the
19 * underlying Jx9 Virtual Machine.
20 */
21/*
22 * string db_version(void)
23 * Return the current version of the unQLite database engine.
24 * Parameter
25 * None
26 * Return
27 * unQLite version number (string).
28 */
29static int unqliteBuiltin_db_version(jx9_context *pCtx,int argc,jx9_value **argv)
30{
31 SXUNUSED(argc); /* cc warning */
32 SXUNUSED(argv);
33 jx9_result_string(pCtx,UNQLITE_VERSION,(int)sizeof(UNQLITE_VERSION)-1);
34 return JX9_OK;
35}
36/*
37 * string db_errlog(void)
38 * Return the database error log.
39 * Parameter
40 * None
41 * Return
42 * Database error log (string).
43 */
44static int unqliteBuiltin_db_errlog(jx9_context *pCtx,int argc,jx9_value **argv)
45{
46 unqlite_vm *pVm;
47 SyBlob *pErr;
48
49 SXUNUSED(argc); /* cc warning */
50 SXUNUSED(argv);
51
52 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
53 /* Point to the error log */
54 pErr = &pVm->pDb->sErr;
55 /* Return the log */
56 jx9_result_string(pCtx,(const char *)SyBlobData(pErr),(int)SyBlobLength(pErr));
57 return JX9_OK;
58}
59/*
60 * string db_copyright(void)
61 * string db_credits(void)
62 * Return the unQLite database engine copyright notice.
63 * Parameter
64 * None
65 * Return
66 * Copyright notice.
67 */
68static int unqliteBuiltin_db_credits(jx9_context *pCtx,int argc,jx9_value **argv)
69{
70 SXUNUSED(argc); /* cc warning */
71 SXUNUSED(argv);
72 jx9_result_string(pCtx,UNQLITE_COPYRIGHT,(int)sizeof(UNQLITE_COPYRIGHT)-1);
73 return JX9_OK;
74}
75/*
76 * string db_sig(void)
77 * Return the unQLite database engine unique signature.
78 * Parameter
79 * None
80 * Return
81 * unQLite signature.
82 */
83static int unqliteBuiltin_db_sig(jx9_context *pCtx,int argc,jx9_value **argv)
84{
85 SXUNUSED(argc); /* cc warning */
86 SXUNUSED(argv);
87 jx9_result_string(pCtx,UNQLITE_IDENT,sizeof(UNQLITE_IDENT)-1);
88 return JX9_OK;
89}
90/*
91 * bool collection_exists(string $name)
92 * bool db_exits(string $name)
93 * Check if a given collection exists in the underlying database.
94 * Parameter
95 * name: Lookup name
96 * Return
97 * TRUE if the collection exits. FALSE otherwise.
98 */
99static int unqliteBuiltin_collection_exists(jx9_context *pCtx,int argc,jx9_value **argv)
100{
101 unqlite_col *pCol;
102 const char *zName;
103 unqlite_vm *pVm;
104 SyString sName;
105 int nByte;
106 /* Extract collection name */
107 if( argc < 1 ){
108 /* Missing arguments */
109 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
110 /* Return false */
111 jx9_result_bool(pCtx,0);
112 return JX9_OK;
113 }
114 zName = jx9_value_to_string(argv[0],&nByte);
115 if( nByte < 1){
116 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
117 /* Return false */
118 jx9_result_bool(pCtx,0);
119 return JX9_OK;
120 }
121 SyStringInitFromBuf(&sName,zName,nByte);
122 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
123 /* Perform the lookup */
124 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
125 /* Lookup result */
126 jx9_result_bool(pCtx,pCol ? 1 : 0);
127 return JX9_OK;
128}
129/*
130 * bool collection_create(string $name)
131 * bool db_create(string $name)
132 * Create a new collection.
133 * Parameter
134 * name: Collection name
135 * Return
136 * TRUE if the collection was successfuly created. FALSE otherwise.
137 */
138static int unqliteBuiltin_collection_create(jx9_context *pCtx,int argc,jx9_value **argv)
139{
140 const char *zName;
141 unqlite_vm *pVm;
142 SyString sName;
143 int nByte;
144 int rc;
145 /* Extract collection name */
146 if( argc < 1 ){
147 /* Missing arguments */
148 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
149 /* Return false */
150 jx9_result_bool(pCtx,0);
151 return JX9_OK;
152 }
153 zName = jx9_value_to_string(argv[0],&nByte);
154 if( nByte < 1){
155 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
156 /* Return false */
157 jx9_result_bool(pCtx,0);
158 return JX9_OK;
159 }
160 SyStringInitFromBuf(&sName,zName,nByte);
161 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
162 /* Try to create the collection */
163 rc = unqliteCreateCollection(pVm,&sName);
164 /* Return the result to the caller */
165 jx9_result_bool(pCtx,rc == UNQLITE_OK ? 1 : 0);
166 return JX9_OK;
167}
168/*
169 * value db_fetch(string $col_name)
170 * value db_get(string $col_name)
171 * Fetch the current record from a given collection and advance
172 * the record cursor.
173 * Parameter
174 * col_name: Collection name
175 * Return
176 * Record content success. NULL on failure (No more records to retrieve).
177 */
178static int unqliteBuiltin_db_fetch_next(jx9_context *pCtx,int argc,jx9_value **argv)
179{
180 unqlite_col *pCol;
181 const char *zName;
182 unqlite_vm *pVm;
183 SyString sName;
184 int nByte;
185 int rc;
186 /* Extract collection name */
187 if( argc < 1 ){
188 /* Missing arguments */
189 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
190 /* Return null */
191 jx9_result_null(pCtx);
192 return JX9_OK;
193 }
194 zName = jx9_value_to_string(argv[0],&nByte);
195 if( nByte < 1){
196 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
197 /* Return null */
198 jx9_result_null(pCtx);
199 return JX9_OK;
200 }
201 SyStringInitFromBuf(&sName,zName,nByte);
202 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
203 /* Fetch the collection */
204 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
205 if( pCol ){
206 /* Fetch the current record */
207 jx9_value *pValue;
208 pValue = jx9_context_new_scalar(pCtx);
209 if( pValue == 0 ){
210 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory");
211 jx9_result_null(pCtx);
212 return JX9_OK;
213 }else{
214 rc = unqliteCollectionFetchNextRecord(pCol,pValue);
215 if( rc == UNQLITE_OK ){
216 jx9_result_value(pCtx,pValue);
217 /* pValue will be automatically released as soon we return from this function */
218 }else{
219 /* Return null */
220 jx9_result_null(pCtx);
221 }
222 }
223 }else{
224 /* No such collection, return null */
225 jx9_result_null(pCtx);
226 }
227 return JX9_OK;
228}
229/*
230 * value db_fetch_by_id(string $col_name,int64 $record_id)
231 * value db_get_by_id(string $col_name,int64 $record_id)
232 * Fetch a record using its unique ID from a given collection.
233 * Parameter
234 * col_name: Collection name
235 * record_id: Record number (__id field of a JSON object)
236 * Return
237 * Record content success. NULL on failure (No such record).
238 */
239static int unqliteBuiltin_db_fetch_by_id(jx9_context *pCtx,int argc,jx9_value **argv)
240{
241 unqlite_col *pCol;
242 const char *zName;
243 unqlite_vm *pVm;
244 SyString sName;
245 jx9_int64 nId;
246 int nByte;
247 int rc;
248 /* Extract collection name */
249 if( argc < 2 ){
250 /* Missing arguments */
251 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or record ID");
252 /* Return NULL */
253 jx9_result_null(pCtx);
254 return JX9_OK;
255 }
256 zName = jx9_value_to_string(argv[0],&nByte);
257 if( nByte < 1){
258 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
259 /* Return NULL */
260 jx9_result_null(pCtx);
261 return JX9_OK;
262 }
263 /* Extract the record ID */
264 nId = jx9_value_to_int(argv[1]);
265 SyStringInitFromBuf(&sName,zName,nByte);
266 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
267 /* Fetch the collection */
268 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
269 if( pCol ){
270 /* Fetch the desired record */
271 jx9_value *pValue;
272 pValue = jx9_context_new_scalar(pCtx);
273 if( pValue == 0 ){
274 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory");
275 jx9_result_null(pCtx);
276 return JX9_OK;
277 }else{
278 rc = unqliteCollectionFetchRecordById(pCol,nId,pValue);
279 if( rc == UNQLITE_OK ){
280 jx9_result_value(pCtx,pValue);
281 /* pValue will be automatically released as soon we return from this function */
282 }else{
283 /* No such record, return null */
284 jx9_result_null(pCtx);
285 }
286 }
287 }else{
288 /* No such collection, return null */
289 jx9_result_null(pCtx);
290 }
291 return JX9_OK;
292}
293/*
294 * array db_fetch_all(string $col_name,[callback filter_callback])
295 * array db_get_all(string $col_name,[callback filter_callback])
296 * Retrieve all records of a given collection and apply the given
297 * callback if available to filter records.
298 * Parameter
299 * col_name: Collection name
300 * Return
301 * Contents of the collection (JSON array) on success. NULL on failure.
302 */
303static int unqliteBuiltin_db_fetch_all(jx9_context *pCtx,int argc,jx9_value **argv)
304{
305 unqlite_col *pCol;
306 const char *zName;
307 unqlite_vm *pVm;
308 SyString sName;
309 int nByte;
310 int rc;
311 /* Extract collection name */
312 if( argc < 1 ){
313 /* Missing arguments */
314 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
315 /* Return NULL */
316 jx9_result_null(pCtx);
317 return JX9_OK;
318 }
319 zName = jx9_value_to_string(argv[0],&nByte);
320 if( nByte < 1){
321 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
322 /* Return NULL */
323 jx9_result_null(pCtx);
324 return JX9_OK;
325 }
326 SyStringInitFromBuf(&sName,zName,nByte);
327 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
328 /* Fetch the collection */
329 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
330 if( pCol ){
331 jx9_value *pValue,*pArray,*pCallback = 0;
332 jx9_value sResult; /* Callback result */
333 /* Allocate an empty scalar value and an empty JSON array */
334 pArray = jx9_context_new_array(pCtx);
335 pValue = jx9_context_new_scalar(pCtx);
336 jx9MemObjInit(pCtx->pVm,&sResult);
337 if( pValue == 0 || pArray == 0 ){
338 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Jx9 is running out of memory");
339 jx9_result_null(pCtx);
340 return JX9_OK;
341 }
342 if( argc > 1 && jx9_value_is_callable(argv[1]) ){
343 pCallback = argv[1];
344 }
345 unqliteCollectionResetRecordCursor(pCol);
346 /* Fetch collection records one after one */
347 while( UNQLITE_OK == unqliteCollectionFetchNextRecord(pCol,pValue) ){
348 if( pCallback ){
349 jx9_value *apArg[2];
350 /* Invoke the filter callback */
351 apArg[0] = pValue;
352 rc = jx9VmCallUserFunction(pCtx->pVm,pCallback,1,apArg,&sResult);
353 if( rc == JX9_OK ){
354 int iResult; /* Callback result */
355 /* Extract callback result */
356 iResult = jx9_value_to_bool(&sResult);
357 if( !iResult ){
358 /* Discard the result */
359 unqliteCollectionCacheRemoveRecord(pCol,unqliteCollectionCurrentRecordId(pCol) - 1);
360 continue;
361 }
362 }
363 }
364 /* Put the value in the JSON array */
365 jx9_array_add_elem(pArray,0,pValue);
366 /* Release the value */
367 jx9_value_null(pValue);
368 }
369 jx9MemObjRelease(&sResult);
370 /* Finally, return our array */
371 jx9_result_value(pCtx,pArray);
372 /* pValue will be automatically released as soon we return from
373 * this foreign function.
374 */
375 }else{
376 /* No such collection, return null */
377 jx9_result_null(pCtx);
378 }
379 return JX9_OK;
380}
381/*
382 * int64 db_last_record_id(string $col_name)
383 * Return the ID of the last inserted record.
384 * Parameter
385 * col_name: Collection name
386 * Return
387 * Record ID (64-bit integer) on success. FALSE on failure.
388 */
389static int unqliteBuiltin_db_last_record_id(jx9_context *pCtx,int argc,jx9_value **argv)
390{
391 unqlite_col *pCol;
392 const char *zName;
393 unqlite_vm *pVm;
394 SyString sName;
395 int nByte;
396 /* Extract collection name */
397 if( argc < 1 ){
398 /* Missing arguments */
399 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
400 /* Return false */
401 jx9_result_bool(pCtx,0);
402 return JX9_OK;
403 }
404 zName = jx9_value_to_string(argv[0],&nByte);
405 if( nByte < 1){
406 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
407 /* Return false */
408 jx9_result_bool(pCtx,0);
409 return JX9_OK;
410 }
411 SyStringInitFromBuf(&sName,zName,nByte);
412 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
413 /* Fetch the collection */
414 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
415 if( pCol ){
416 jx9_result_int64(pCtx,unqliteCollectionLastRecordId(pCol));
417 }else{
418 /* No such collection, return FALSE */
419 jx9_result_bool(pCtx,0);
420 }
421 return JX9_OK;
422}
423/*
424 * inr64 db_current_record_id(string $col_name)
425 * Return the current record ID.
426 * Parameter
427 * col_name: Collection name
428 * Return
429 * Current record ID (64-bit integer) on success. FALSE on failure.
430 */
431static int unqliteBuiltin_db_current_record_id(jx9_context *pCtx,int argc,jx9_value **argv)
432{
433 unqlite_col *pCol;
434 const char *zName;
435 unqlite_vm *pVm;
436 SyString sName;
437 int nByte;
438 /* Extract collection name */
439 if( argc < 1 ){
440 /* Missing arguments */
441 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
442 /* Return false */
443 jx9_result_bool(pCtx,0);
444 return JX9_OK;
445 }
446 zName = jx9_value_to_string(argv[0],&nByte);
447 if( nByte < 1){
448 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
449 /* Return false */
450 jx9_result_bool(pCtx,0);
451 return JX9_OK;
452 }
453 SyStringInitFromBuf(&sName,zName,nByte);
454 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
455 /* Fetch the collection */
456 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
457 if( pCol ){
458 jx9_result_int64(pCtx,unqliteCollectionCurrentRecordId(pCol));
459 }else{
460 /* No such collection, return FALSE */
461 jx9_result_bool(pCtx,0);
462 }
463 return JX9_OK;
464}
465/*
466 * bool db_reset_record_cursor(string $col_name)
467 * Reset the record ID cursor.
468 * Parameter
469 * col_name: Collection name
470 * Return
471 * TRUE on success. FALSE on failure.
472 */
473static int unqliteBuiltin_db_reset_record_cursor(jx9_context *pCtx,int argc,jx9_value **argv)
474{
475 unqlite_col *pCol;
476 const char *zName;
477 unqlite_vm *pVm;
478 SyString sName;
479 int nByte;
480 /* Extract collection name */
481 if( argc < 1 ){
482 /* Missing arguments */
483 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
484 /* Return false */
485 jx9_result_bool(pCtx,0);
486 return JX9_OK;
487 }
488 zName = jx9_value_to_string(argv[0],&nByte);
489 if( nByte < 1){
490 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
491 /* Return false */
492 jx9_result_bool(pCtx,0);
493 return JX9_OK;
494 }
495 SyStringInitFromBuf(&sName,zName,nByte);
496 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
497 /* Fetch the collection */
498 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
499 if( pCol ){
500 unqliteCollectionResetRecordCursor(pCol);
501 jx9_result_bool(pCtx,1);
502 }else{
503 /* No such collection */
504 jx9_result_bool(pCtx,0);
505 }
506 return JX9_OK;
507}
508/*
509 * int64 db_total_records(string $col_name)
510 * Return the total number of inserted records in the given collection.
511 * Parameter
512 * col_name: Collection name
513 * Return
514 * Total number of records on success. FALSE on failure.
515 */
516static int unqliteBuiltin_db_total_records(jx9_context *pCtx,int argc,jx9_value **argv)
517{
518 unqlite_col *pCol;
519 const char *zName;
520 unqlite_vm *pVm;
521 SyString sName;
522 int nByte;
523 /* Extract collection name */
524 if( argc < 1 ){
525 /* Missing arguments */
526 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
527 /* Return false */
528 jx9_result_bool(pCtx,0);
529 return JX9_OK;
530 }
531 zName = jx9_value_to_string(argv[0],&nByte);
532 if( nByte < 1){
533 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
534 /* Return false */
535 jx9_result_bool(pCtx,0);
536 return JX9_OK;
537 }
538 SyStringInitFromBuf(&sName,zName,nByte);
539 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
540 /* Fetch the collection */
541 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
542 if( pCol ){
543 unqlite_int64 nRec;
544 nRec = unqliteCollectionTotalRecords(pCol);
545 jx9_result_int64(pCtx,nRec);
546 }else{
547 /* No such collection */
548 jx9_result_bool(pCtx,0);
549 }
550 return JX9_OK;
551}
552/*
553 * string db_creation_date(string $col_name)
554 * Return the creation date of the given collection.
555 * Parameter
556 * col_name: Collection name
557 * Return
558 * Creation date on success. FALSE on failure.
559 */
560static int unqliteBuiltin_db_creation_date(jx9_context *pCtx,int argc,jx9_value **argv)
561{
562 unqlite_col *pCol;
563 const char *zName;
564 unqlite_vm *pVm;
565 SyString sName;
566 int nByte;
567 /* Extract collection name */
568 if( argc < 1 ){
569 /* Missing arguments */
570 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
571 /* Return false */
572 jx9_result_bool(pCtx,0);
573 return JX9_OK;
574 }
575 zName = jx9_value_to_string(argv[0],&nByte);
576 if( nByte < 1){
577 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
578 /* Return false */
579 jx9_result_bool(pCtx,0);
580 return JX9_OK;
581 }
582 SyStringInitFromBuf(&sName,zName,nByte);
583 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
584 /* Fetch the collection */
585 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
586 if( pCol ){
587 Sytm *pTm = &pCol->sCreation;
588 jx9_result_string_format(pCtx,"%d-%d-%d %02d:%02d:%02d",
589 pTm->tm_year,pTm->tm_mon,pTm->tm_mday,
590 pTm->tm_hour,pTm->tm_min,pTm->tm_sec
591 );
592 }else{
593 /* No such collection */
594 jx9_result_bool(pCtx,0);
595 }
596 return JX9_OK;
597}
598/*
599 * bool db_store(string $col_name,...)
600 * bool db_put(string $col_name,...)
601 * Store one or more JSON values in a given collection.
602 * Parameter
603 * col_name: Collection name
604 * Return
605 * TRUE on success. FALSE on failure.
606 */
607static int unqliteBuiltin_db_store(jx9_context *pCtx,int argc,jx9_value **argv)
608{
609 unqlite_col *pCol;
610 const char *zName;
611 unqlite_vm *pVm;
612 SyString sName;
613 int nByte;
614 int rc;
615 int i;
616 /* Extract collection name */
617 if( argc < 2 ){
618 /* Missing arguments */
619 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or records");
620 /* Return false */
621 jx9_result_bool(pCtx,0);
622 return JX9_OK;
623 }
624 zName = jx9_value_to_string(argv[0],&nByte);
625 if( nByte < 1){
626 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
627 /* Return false */
628 jx9_result_bool(pCtx,0);
629 return JX9_OK;
630 }
631 SyStringInitFromBuf(&sName,zName,nByte);
632 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
633 /* Fetch the collection */
634 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
635 if( pCol == 0 ){
636 jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName);
637 /* Return false */
638 jx9_result_bool(pCtx,0);
639 return JX9_OK;
640 }
641 /* Store the given values */
642 for( i = 1 ; i < argc ; ++i ){
643 rc = unqliteCollectionPut(pCol,argv[i],0);
644 if( rc != UNQLITE_OK){
645 jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,
646 "Error while storing record %d in collection '%z'",i,&sName
647 );
648 /* Return false */
649 jx9_result_bool(pCtx,0);
650 return JX9_OK;
651 }
652 }
653 /* All done, return TRUE */
654 jx9_result_bool(pCtx,1);
655 return JX9_OK;
656}
657/*
658 * bool db_drop_collection(string $col_name)
659 * bool collection_delete(string $col_name)
660 * Remove a given collection from the database.
661 * Parameter
662 * col_name: Collection name
663 * Return
664 * TRUE on success. FALSE on failure.
665 */
666static int unqliteBuiltin_db_drop_col(jx9_context *pCtx,int argc,jx9_value **argv)
667{
668 unqlite_col *pCol;
669 const char *zName;
670 unqlite_vm *pVm;
671 SyString sName;
672 int nByte;
673 int rc;
674 /* Extract collection name */
675 if( argc < 1 ){
676 /* Missing arguments */
677 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name");
678 /* Return false */
679 jx9_result_bool(pCtx,0);
680 return JX9_OK;
681 }
682 zName = jx9_value_to_string(argv[0],&nByte);
683 if( nByte < 1){
684 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
685 /* Return false */
686 jx9_result_bool(pCtx,0);
687 return JX9_OK;
688 }
689 SyStringInitFromBuf(&sName,zName,nByte);
690 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
691 /* Fetch the collection */
692 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
693 if( pCol == 0 ){
694 jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName);
695 /* Return false */
696 jx9_result_bool(pCtx,0);
697 return JX9_OK;
698 }
699 /* Drop the collection */
700 rc = unqliteDropCollection(pCol);
701 /* Processing result */
702 jx9_result_bool(pCtx,rc == UNQLITE_OK);
703 return JX9_OK;
704}
705/*
706 * bool db_drop_record(string $col_name,int64 record_id)
707 * Remove a given record from a collection.
708 * Parameter
709 * col_name: Collection name.
710 * record_id: ID of the record.
711 * Return
712 * TRUE on success. FALSE on failure.
713 */
714static int unqliteBuiltin_db_drop_record(jx9_context *pCtx,int argc,jx9_value **argv)
715{
716 unqlite_col *pCol;
717 const char *zName;
718 unqlite_vm *pVm;
719 SyString sName;
720 jx9_int64 nId;
721 int nByte;
722 int rc;
723 /* Extract collection name */
724 if( argc < 2 ){
725 /* Missing arguments */
726 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or records");
727 /* Return false */
728 jx9_result_bool(pCtx,0);
729 return JX9_OK;
730 }
731 zName = jx9_value_to_string(argv[0],&nByte);
732 if( nByte < 1){
733 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
734 /* Return false */
735 jx9_result_bool(pCtx,0);
736 return JX9_OK;
737 }
738 SyStringInitFromBuf(&sName,zName,nByte);
739 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
740 /* Fetch the collection */
741 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
742 if( pCol == 0 ){
743 jx9_context_throw_error_format(pCtx,JX9_CTX_ERR,"No such collection '%z'",&sName);
744 /* Return false */
745 jx9_result_bool(pCtx,0);
746 return JX9_OK;
747 }
748 /* Extract the record ID */
749 nId = jx9_value_to_int64(argv[1]);
750 /* Drop the record */
751 rc = unqliteCollectionDropRecord(pCol,nId,1,1);
752 /* Processing result */
753 jx9_result_bool(pCtx,rc == UNQLITE_OK);
754 return JX9_OK;
755}
756/*
757 * bool db_set_schema(string $col_name, object $json_object)
758 * Set a schema for a given collection.
759 * Parameter
760 * col_name: Collection name.
761 * json_object: Collection schema (Must be a JSON object).
762 * Return
763 * TRUE on success. FALSE on failure.
764 */
765static int unqliteBuiltin_db_set_schema(jx9_context *pCtx,int argc,jx9_value **argv)
766{
767 unqlite_col *pCol;
768 const char *zName;
769 unqlite_vm *pVm;
770 SyString sName;
771 int nByte;
772 int rc;
773 /* Extract collection name */
774 if( argc < 2 ){
775 /* Missing arguments */
776 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or db scheme");
777 /* Return false */
778 jx9_result_bool(pCtx,0);
779 return JX9_OK;
780 }
781 if( !jx9_value_is_json_object(argv[1]) ){
782 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection scheme");
783 /* Return false */
784 jx9_result_bool(pCtx,0);
785 return JX9_OK;
786 }
787 zName = jx9_value_to_string(argv[0],&nByte);
788 if( nByte < 1){
789 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
790 /* Return false */
791 jx9_result_bool(pCtx,0);
792 return JX9_OK;
793 }
794 SyStringInitFromBuf(&sName,zName,nByte);
795 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
796 /* Fetch the collection */
797 rc = UNQLITE_NOOP;
798 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
799 if( pCol ){
800 /* Set the collection scheme */
801 rc = unqliteCollectionSetSchema(pCol,argv[1]);
802 }else{
803 jx9_context_throw_error_format(pCtx,JX9_CTX_WARNING,
804 "No such collection '%z'",
805 &sName
806 );
807 }
808 /* Processing result */
809 jx9_result_bool(pCtx,rc == UNQLITE_OK);
810 return JX9_OK;
811}
812/*
813 * object db_get_schema(string $col_name)
814 * Return the schema associated with a given collection.
815 * Parameter
816 * col_name: Collection name
817 * Return
818 * Collection schema on success. null otherwise.
819 */
820static int unqliteBuiltin_db_get_schema(jx9_context *pCtx,int argc,jx9_value **argv)
821{
822 unqlite_col *pCol;
823 const char *zName;
824 unqlite_vm *pVm;
825 SyString sName;
826 int nByte;
827 /* Extract collection name */
828 if( argc < 1 ){
829 /* Missing arguments */
830 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Missing collection name and/or db scheme");
831 /* Return false */
832 jx9_result_bool(pCtx,0);
833 return JX9_OK;
834 }
835 zName = jx9_value_to_string(argv[0],&nByte);
836 if( nByte < 1){
837 jx9_context_throw_error(pCtx,JX9_CTX_ERR,"Invalid collection name");
838 /* Return false */
839 jx9_result_bool(pCtx,0);
840 return JX9_OK;
841 }
842 SyStringInitFromBuf(&sName,zName,nByte);
843 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
844 /* Fetch the collection */
845 pCol = unqliteCollectionFetch(pVm,&sName,UNQLITE_VM_AUTO_LOAD);
846 if( pCol ){
847 /* Return the collection schema */
848 jx9_result_value(pCtx,&pCol->sSchema);
849 }else{
850 jx9_context_throw_error_format(pCtx,JX9_CTX_WARNING,
851 "No such collection '%z'",
852 &sName
853 );
854 jx9_result_null(pCtx);
855 }
856 return JX9_OK;
857}
858/*
859 * bool db_begin(void)
860 * Manually begin a write transaction.
861 * Parameter
862 * None
863 * Return
864 * TRUE on success. FALSE otherwise.
865 */
866static int unqliteBuiltin_db_begin(jx9_context *pCtx,int argc,jx9_value **argv)
867{
868 unqlite_vm *pVm;
869 unqlite *pDb;
870 int rc;
871 SXUNUSED(argc); /* cc warning */
872 SXUNUSED(argv);
873 /* Point to the unqlite Vm */
874 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
875 /* Point to the underlying database handle */
876 pDb = pVm->pDb;
877 /* Begin the transaction */
878 rc = unqlitePagerBegin(pDb->sDB.pPager);
879 /* result */
880 jx9_result_bool(pCtx,rc == UNQLITE_OK );
881 return JX9_OK;
882}
883/*
884 * bool db_commit(void)
885 * Manually commit a transaction.
886 * Parameter
887 * None
888 * Return
889 * TRUE if the transaction was successfuly commited. FALSE otherwise.
890 */
891static int unqliteBuiltin_db_commit(jx9_context *pCtx,int argc,jx9_value **argv)
892{
893 unqlite_vm *pVm;
894 unqlite *pDb;
895 int rc;
896 SXUNUSED(argc); /* cc warning */
897 SXUNUSED(argv);
898 /* Point to the unqlite Vm */
899 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
900 /* Point to the underlying database handle */
901 pDb = pVm->pDb;
902 /* Commit the transaction if any */
903 rc = unqlitePagerCommit(pDb->sDB.pPager);
904 /* Commit result */
905 jx9_result_bool(pCtx,rc == UNQLITE_OK );
906 return JX9_OK;
907}
908/*
909 * bool db_rollback(void)
910 * Manually rollback a transaction.
911 * Parameter
912 * None
913 * Return
914 * TRUE if the transaction was successfuly rolled back. FALSE otherwise
915 */
916static int unqliteBuiltin_db_rollback(jx9_context *pCtx,int argc,jx9_value **argv)
917{
918 unqlite_vm *pVm;
919 unqlite *pDb;
920 int rc;
921 SXUNUSED(argc); /* cc warning */
922 SXUNUSED(argv);
923 /* Point to the unqlite Vm */
924 pVm = (unqlite_vm *)jx9_context_user_data(pCtx);
925 /* Point to the underlying database handle */
926 pDb = pVm->pDb;
927 /* Rollback the transaction if any */
928 rc = unqlitePagerRollback(pDb->sDB.pPager,TRUE);
929 /* Rollback result */
930 jx9_result_bool(pCtx,rc == UNQLITE_OK );
931 return JX9_OK;
932}
933/*
934 * Register all the UnQLite foreign functions defined above.
935 */
936UNQLITE_PRIVATE int unqliteRegisterJx9Functions(unqlite_vm *pVm)
937{
938 static const jx9_builtin_func aBuiltin[] = {
939 { "db_version" , unqliteBuiltin_db_version },
940 { "db_copyright", unqliteBuiltin_db_credits },
941 { "db_credits" , unqliteBuiltin_db_credits },
942 { "db_sig" , unqliteBuiltin_db_sig },
943 { "db_errlog", unqliteBuiltin_db_errlog },
944 { "collection_exists", unqliteBuiltin_collection_exists },
945 { "db_exists", unqliteBuiltin_collection_exists },
946 { "collection_create", unqliteBuiltin_collection_create },
947 { "db_create", unqliteBuiltin_collection_create },
948 { "db_fetch", unqliteBuiltin_db_fetch_next },
949 { "db_get", unqliteBuiltin_db_fetch_next },
950 { "db_fetch_by_id", unqliteBuiltin_db_fetch_by_id },
951 { "db_get_by_id", unqliteBuiltin_db_fetch_by_id },
952 { "db_fetch_all", unqliteBuiltin_db_fetch_all },
953 { "db_get_all", unqliteBuiltin_db_fetch_all },
954 { "db_last_record_id", unqliteBuiltin_db_last_record_id },
955 { "db_current_record_id", unqliteBuiltin_db_current_record_id },
956 { "db_reset_record_cursor", unqliteBuiltin_db_reset_record_cursor },
957 { "db_total_records", unqliteBuiltin_db_total_records },
958 { "db_creation_date", unqliteBuiltin_db_creation_date },
959 { "db_store", unqliteBuiltin_db_store },
960 { "db_put", unqliteBuiltin_db_store },
961 { "db_drop_collection", unqliteBuiltin_db_drop_col },
962 { "collection_delete", unqliteBuiltin_db_drop_col },
963 { "db_drop_record", unqliteBuiltin_db_drop_record },
964 { "db_set_schema", unqliteBuiltin_db_set_schema },
965 { "db_get_schema", unqliteBuiltin_db_get_schema },
966 { "db_begin", unqliteBuiltin_db_begin },
967 { "db_commit", unqliteBuiltin_db_commit },
968 { "db_rollback", unqliteBuiltin_db_rollback },
969 };
970 int rc = UNQLITE_OK;
971 sxu32 n;
972 /* Register the unQLite functions defined above in the Jx9 call table */
973 for( n = 0 ; n < SX_ARRAYSIZE(aBuiltin) ; ++n ){
974 rc = jx9_create_function(pVm->pJx9Vm,aBuiltin[n].zName,aBuiltin[n].xFunc,pVm);
975 }
976 return rc;
977}