Skip to content

Commit bee59c0

Browse files
committedFeb 1, 2022
New feature: rounding to fixed decimal precision
1 parent 55ff859 commit bee59c0

File tree

1 file changed

+67
-23
lines changed

1 file changed

+67
-23
lines changed
 

‎floataway.c

+67-23
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ static void jsonWrongNumArgs(
312312
char *zMsg = sqlite3_mprintf("json_%s() needs an odd number of arguments",
313313
zFuncName);
314314
sqlite3_result_error(pCtx, zMsg, -1);
315-
sqlite3_free(zMsg);
315+
sqlite3_free(zMsg);
316316
}
317317

318318

@@ -392,8 +392,11 @@ static void float32NullFunc(
392392
/* An instance of the CSV virtual table */
393393
typedef struct CsvTable {
394394
sqlite3_vtab base; /* Base class. Must be first */
395-
long iStart; /* Offset to start of data in zFilename */
396395
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 */
397400
unsigned int tstFlags; /* Bit values used for testing */
398401
} CsvTable;
399402

@@ -409,13 +412,16 @@ struct JsonEachCursor {
409412
/* Constructor for the json_each virtual table.
410413
** Usage:
411414
** 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=);
413416
**
414417
** Arguments:
415418
** N = number of columns.
416419
** prefix and suffix: e.g.,
417420
** Given (9,col), columns will be named nrow,col1 ... col9.
418421
** 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.
419425
** All arguments are optional but must appear in order,
420426
** with or without argument names. Do not quote strings.
421427
*/
@@ -440,10 +446,15 @@ static int jsonEachConnect(
440446
UNUSED_PARAM(pzErr);
441447
UNUSED_PARAM(pAux);
442448

443-
int nCol = 1; int nColDigits = 1;
449+
int nCol = 1;
450+
int nColDigits = 1;
444451
std::string zColPrefix("col");
445452
std::string zColSuffix("");
446453
std::string zRowName("nrow");
454+
bool bRound = false;
455+
int nRound = -1;
456+
double xRound = 1.0;
457+
double yRound = 1.0;
447458
/* Determine the parameter N = number of columns.
448459
** Take the first user argument if it exists, e.g. argv[3].
449460
** Otherwise default to N = 1.
@@ -455,11 +466,15 @@ static int jsonEachConnect(
455466
std::regex rx(R"""((?:\s*N\s*=)?\s*(\d+)\s*)"""); // no double backslashes with raw string literal
456467
std::smatch match;
457468
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) {
463478
//silently ignore the error
464479
}
465480
} else {
@@ -502,6 +517,31 @@ static int jsonEachConnect(
502517
//silently ignore the error
503518
}
504519
}
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+
505545
nColDigits = 1+(int)log10(nCol); // e.g. 1 -> 1, 9 -> 1, 10 -> 2, 99 -> 2, etc.
506546
std::ostringstream schema;
507547
schema << "CREATE TABLE x(data HIDDEN";
@@ -522,6 +562,10 @@ static int jsonEachConnect(
522562
}
523563
memset(pNew, 0, sizeof(*pNew));
524564
pNew->nCol = nCol;
565+
pNew->bRound = bRound;
566+
pNew->nRound = nRound;
567+
pNew->xRound = xRound;
568+
pNew->yRound = yRound;
525569
sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
526570
}
527571
return rc;
@@ -561,15 +605,6 @@ static int jsonEachOpenEach(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
561605
return SQLITE_OK;
562606
}
563607

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-
573608
/* Reset a JsonEachCursor back to its original state. Free any memory
574609
** held. */
575610
static void jsonEachCursorReset(JsonEachCursor *p){
@@ -624,7 +659,16 @@ static int jsonEachColumn(
624659
int iCol = i - JEACH_VALUE;
625660
assert( i >= JEACH_VALUE );
626661
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+
}
628672
break;
629673
}
630674
}
@@ -790,7 +834,7 @@ int sqlite3Json1Init(sqlite3 *db){
790834
int nArg;
791835
int flag;
792836
} aFunc[] = {
793-
837+
794838
{ "float32Null", float32NullFunc, 1, 0 },
795839

796840
#if SQLITE_DEBUG
@@ -816,7 +860,7 @@ int sqlite3Json1Init(sqlite3 *db){
816860
{ "float_each", &jsonEachModule },
817861
};
818862
#endif
819-
static const int enc =
863+
static const int enc =
820864
SQLITE_UTF8 |
821865
SQLITE_DETERMINISTIC |
822866
SQLITE_INNOCUOUS;
@@ -843,8 +887,8 @@ extern "C"
843887
__declspec(dllexport)
844888
#endif
845889
int sqlite3_floataway_init(
846-
sqlite3 *db,
847-
char **pzErrMsg,
890+
sqlite3 *db,
891+
char **pzErrMsg,
848892
const sqlite3_api_routines *pApi
849893
){
850894
SQLITE_EXTENSION_INIT2(pApi);

0 commit comments

Comments
 (0)
Please sign in to comment.