@@ -312,7 +312,7 @@ static void jsonWrongNumArgs(
312
312
char * zMsg = sqlite3_mprintf ("json_%s() needs an odd number of arguments" ,
313
313
zFuncName );
314
314
sqlite3_result_error (pCtx , zMsg , -1 );
315
- sqlite3_free (zMsg );
315
+ sqlite3_free (zMsg );
316
316
}
317
317
318
318
@@ -392,8 +392,11 @@ static void float32NullFunc(
392
392
/* An instance of the CSV virtual table */
393
393
typedef struct CsvTable {
394
394
sqlite3_vtab base ; /* Base class. Must be first */
395
- long iStart ; /* Offset to start of data in zFilename */
396
395
int nCol ; /* Number of columns in the CSV file */
396
+ bool bRound ; /* Whether to round off results to fixed precision */
397
+ int nRound ; /* Number of digits fixed precision if rounding */
398
+ double xRound ; /* Used for rounding calcs */
399
+ double yRound ; /* Used for rounding calcs */
397
400
unsigned int tstFlags ; /* Bit values used for testing */
398
401
} CsvTable ;
399
402
@@ -409,13 +412,16 @@ struct JsonEachCursor {
409
412
/* Constructor for the json_each virtual table.
410
413
** Usage:
411
414
** CREATE VIRTUAL TABLE temp.t1 USING float_each(
412
- ** N=1, prefix=col, suffix=, rowname=nrow);
415
+ ** N=1, prefix=col, suffix=, rowname=nrow, fix= );
413
416
**
414
417
** Arguments:
415
418
** N = number of columns.
416
419
** prefix and suffix: e.g.,
417
420
** Given (9,col), columns will be named nrow,col1 ... col9.
418
421
** Given (10,hr,a), columns will be named nrow,hr01a ... hr10a.
422
+ ** rowname = name to give the leftmost column. This column's value
423
+ ** will be integers starting at 1.
424
+ ** fix = number of digits to round. Leave blank to skip rounding.
419
425
** All arguments are optional but must appear in order,
420
426
** with or without argument names. Do not quote strings.
421
427
*/
@@ -440,10 +446,15 @@ static int jsonEachConnect(
440
446
UNUSED_PARAM (pzErr );
441
447
UNUSED_PARAM (pAux );
442
448
443
- int nCol = 1 ; int nColDigits = 1 ;
449
+ int nCol = 1 ;
450
+ int nColDigits = 1 ;
444
451
std ::string zColPrefix ("col" );
445
452
std ::string zColSuffix ("");
446
453
std ::string zRowName ("nrow" );
454
+ bool bRound = false;
455
+ int nRound = -1 ;
456
+ double xRound = 1.0 ;
457
+ double yRound = 1.0 ;
447
458
/* Determine the parameter N = number of columns.
448
459
** Take the first user argument if it exists, e.g. argv[3].
449
460
** Otherwise default to N = 1.
@@ -455,11 +466,15 @@ static int jsonEachConnect(
455
466
std ::regex rx (R "" "((?:\s*N\s*=)?\s*(\d+)\s*)" "" ); // no double backslashes with raw string literal
456
467
std ::smatch match ;
457
468
if (regex_match (target .cbegin (), target .cend (), match , rx )) {
458
- // Regex found
459
- int nColFound = std ::stoi (match .str (1 ));
460
- if (nColFound >= 1 ) {
461
- nCol = nColFound ;
462
- } else {
469
+ try {
470
+ // Regex found
471
+ int nColFound = std ::stoi (match .str (1 ));
472
+ if (nColFound >= 1 ) {
473
+ nCol = nColFound ;
474
+ } else {
475
+ //silently ignore the error
476
+ }
477
+ } catch (std ::logic_error & e ) {
463
478
//silently ignore the error
464
479
}
465
480
} else {
@@ -502,6 +517,31 @@ static int jsonEachConnect(
502
517
//silently ignore the error
503
518
}
504
519
}
520
+ if (argc > 7 ) {
521
+ std ::string target (argv [7 ]);
522
+ // fix=4
523
+ std ::regex rx (R "" "((?:\s*fix\s*=)?\s*(\d+)\s*)" "" );
524
+ std ::smatch match ;
525
+ if (regex_match (target .cbegin (), target .cend (), match , rx )) {
526
+ // Regex found
527
+ try {
528
+ int nRndArg = std ::stoi (match .str (1 ));
529
+ if (nRndArg > 0 ) {
530
+ bRound = true;
531
+ nRound = nRndArg ;
532
+ xRound = pow (10.0 , nRound );
533
+ yRound = 1.0 / xRound ;
534
+ } else {
535
+ //silently ignore the error
536
+ }
537
+ } catch (std ::logic_error & e ) {
538
+ //silently ignore the error
539
+ }
540
+ } else {
541
+ //silently ignore the error
542
+ }
543
+ }
544
+
505
545
nColDigits = 1 + (int )log10 (nCol ); // e.g. 1 -> 1, 9 -> 1, 10 -> 2, 99 -> 2, etc.
506
546
std ::ostringstream schema ;
507
547
schema << "CREATE TABLE x(data HIDDEN" ;
@@ -522,6 +562,10 @@ static int jsonEachConnect(
522
562
}
523
563
memset (pNew , 0 , sizeof (* pNew ));
524
564
pNew -> nCol = nCol ;
565
+ pNew -> bRound = bRound ;
566
+ pNew -> nRound = nRound ;
567
+ pNew -> xRound = xRound ;
568
+ pNew -> yRound = yRound ;
525
569
sqlite3_vtab_config (db , SQLITE_VTAB_INNOCUOUS );
526
570
}
527
571
return rc ;
@@ -561,15 +605,6 @@ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
561
605
return SQLITE_OK ;
562
606
}
563
607
564
- /* constructor for a JsonEachCursor object for json_tree(). */
565
- static int jsonEachOpenTree (sqlite3_vtab * p , sqlite3_vtab_cursor * * ppCursor ){
566
- int rc = jsonEachOpenEach (p , ppCursor );
567
- if ( rc == SQLITE_OK ){
568
- JsonEachCursor * pCur = (JsonEachCursor * )* ppCursor ;
569
- }
570
- return rc ;
571
- }
572
-
573
608
/* Reset a JsonEachCursor back to its original state. Free any memory
574
609
** held. */
575
610
static void jsonEachCursorReset (JsonEachCursor * p ){
@@ -624,7 +659,16 @@ static int jsonEachColumn(
624
659
int iCol = i - JEACH_VALUE ;
625
660
assert ( i >= JEACH_VALUE );
626
661
assert ( i < pTab -> nCol );
627
- sqlite3_result_double (ctx , (double )p -> zJson [pTab -> nCol * p -> iRowid + iCol ]);
662
+ if (pTab -> bRound ) {
663
+ sqlite3_result_double (
664
+ ctx ,
665
+ pTab -> yRound * round (
666
+ pTab -> xRound * (double )p -> zJson [pTab -> nCol * p -> iRowid + iCol ]
667
+ )
668
+ );
669
+ } else {
670
+ sqlite3_result_double (ctx , (double )p -> zJson [pTab -> nCol * p -> iRowid + iCol ]);
671
+ }
628
672
break ;
629
673
}
630
674
}
@@ -790,7 +834,7 @@ int sqlite3Json1Init(sqlite3 *db){
790
834
int nArg ;
791
835
int flag ;
792
836
} aFunc [] = {
793
-
837
+
794
838
{ "float32Null" , float32NullFunc , 1 , 0 },
795
839
796
840
#if SQLITE_DEBUG
@@ -816,7 +860,7 @@ int sqlite3Json1Init(sqlite3 *db){
816
860
{ "float_each" , & jsonEachModule },
817
861
};
818
862
#endif
819
- static const int enc =
863
+ static const int enc =
820
864
SQLITE_UTF8 |
821
865
SQLITE_DETERMINISTIC |
822
866
SQLITE_INNOCUOUS ;
@@ -843,8 +887,8 @@ extern "C"
843
887
__declspec(dllexport )
844
888
#endif
845
889
int sqlite3_floataway_init (
846
- sqlite3 * db ,
847
- char * * pzErrMsg ,
890
+ sqlite3 * db ,
891
+ char * * pzErrMsg ,
848
892
const sqlite3_api_routines * pApi
849
893
){
850
894
SQLITE_EXTENSION_INIT2 (pApi );
0 commit comments