@@ -229,6 +229,295 @@ static void sqlite3_strftime(sqlite3_context *context, int argc, sqlite3_value *
229229 sqlite3_result_text (context , buf , -1 , SQLITE_TRANSIENT );
230230}
231231
232+ /*
233+ * Uses any integer. It provides the category that integer is in from
234+ * Zero, O for less than 1000, K for less than 1 million, M less than
235+ * billion, B for less than Trillion, T for less than quadrillion, q
236+ * for less than quintillion, Q for more than Quintillion. (using
237+ * 1000)
238+ *
239+ * Usage:
240+ * SELECT COUNT(*), intcat(int) AS cat
241+ * FROM ..
242+ * GROUP BY cat;
243+ */
244+ static void intcat (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
245+ (void ) argc ;
246+
247+ static const double itK = 1000ULL ;
248+ static const double itM = 1000ULL * 1000ULL ;
249+ static const double itB = 1000ULL * 1000ULL * 1000ULL ;
250+ static const double itT = 1000ULL * 1000ULL * 1000ULL * 1000ULL ;
251+ static const double itq = 1000ULL * 1000ULL * 1000ULL * 1000ULL * 1000ULL ;
252+ static const double itQ = 1000ULL * 1000ULL * 1000ULL * 1000ULL * 1000ULL * 1000ULL ;
253+
254+ const char * intin_s = (const char * ) sqlite3_value_text (argv [0 ]);
255+
256+ double intin = 0 ;
257+ if (sscanf (intin_s , "%lf" , & intin ) != 1 ) {
258+ sqlite3_result_error (context , "Bad size" , -1 );
259+ return ;
260+ }
261+
262+ if (intin < 0 ) {
263+ sqlite3_result_error (context , "Bad size" , -1 );
264+ return ;
265+ }
266+
267+ char returnintcat [8 ];
268+
269+ if (intin == 0 ) {
270+ sprintf (returnintcat , "%s" , "Zero" );
271+ }
272+ else if (intin < itK ) {
273+ sprintf (returnintcat , "%s" , "O" );
274+ }
275+ else if (intin < itM ) {
276+ sprintf (returnintcat , "%s" , "K" );
277+ }
278+ else if (intin < itB ) {
279+ sprintf (returnintcat , "%s" , "M" );
280+ }
281+ else if (intin < itT ) {
282+ sprintf (returnintcat , "%s" , "B" );
283+ }
284+ else if (intin < itq ) {
285+ sprintf (returnintcat , "%s" , "T" );
286+ }
287+ else if (intin < itQ ) {
288+ sprintf (returnintcat , "%s" , "q" );
289+ }
290+ else {
291+ sprintf (returnintcat , "%s" , "Q" );
292+ }
293+
294+ sqlite3_result_text (context , returnintcat , -1 , SQLITE_TRANSIENT );
295+ }
296+
297+ /*
298+ * Uses any integer. Provides category from Zero, B for less than 1k,
299+ * K for less than 1M, M for less than 1G, G for less than 1T, T for
300+ * less than one P, P for less than 1E, E for more than 1E. (using
301+ * 1024)
302+ *
303+ * Usage:
304+ * SELECT COUNT(*), bytecat(int) AS cat
305+ * FROM ..
306+ * GROUP BY cat;
307+ */
308+ static void bytecat (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
309+ (void ) argc ;
310+
311+ static const double btk = 1024ULL ;
312+ static const double btm = 1024ULL * 1024ULL ;
313+ static const double btg = 1024ULL * 1024ULL * 1024ULL ;
314+ static const double btt = 1024ULL * 1024ULL * 1024ULL * 1024ULL ;
315+ static const double btp = 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL ;
316+ static const double bte = 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL ;
317+
318+ const char * bytein_s = (const char * ) sqlite3_value_text (argv [0 ]);
319+ fprintf (stderr , "%s %lf %lf\n" , bytein_s , btp , bte );
320+
321+ double bytein = 0 ;
322+ if (sscanf (bytein_s , "%lf" , & bytein ) != 1 ) {
323+ sqlite3_result_error (context , "Bad size" , -1 );
324+ return ;
325+ }
326+
327+ if (bytein < 0 ) {
328+ sqlite3_result_error (context , "Bad size" , -1 );
329+ return ;
330+ }
331+
332+ char returnbytecat [8 ];
333+
334+ if (bytein == 0 ) {
335+ sprintf (returnbytecat , "%s" , "Zero" );
336+ }
337+ else if (bytein < btk ) {
338+ sprintf (returnbytecat , "%s" , "B" );
339+ }
340+ else if (bytein < btm ) {
341+ sprintf (returnbytecat , "%s" , "K" );
342+ }
343+ else if (bytein < btg ) {
344+ sprintf (returnbytecat , "%s" , "M" );
345+ }
346+ else if (bytein < btt ) {
347+ sprintf (returnbytecat , "%s" , "G" );
348+ }
349+ else if (bytein < btp ) {
350+ sprintf (returnbytecat , "%s" , "T" );
351+ }
352+ else if (bytein < bte ) {
353+ sprintf (returnbytecat , "%s" , "P" );
354+ }
355+ else {
356+ sprintf (returnbytecat , "%s" , "E" );
357+ }
358+
359+ sqlite3_result_text (context , returnbytecat , -1 , SQLITE_TRANSIENT );
360+ }
361+
362+ /*
363+ * Uses any unix epoch like mtime as input. It subtracts that from
364+ * current time and categorizes into S seconds, M minutes, H hours, d
365+ * days, W weeks, M months, Y years, D decades as categories. (for use
366+ * in group by)
367+ *
368+ * Usage:
369+ * SELECT COUNT(*), agecat(time) AS cat
370+ * FROM ..
371+ * GROUP BY cat;
372+ */
373+ static void agecat (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
374+ (void ) argc ;
375+
376+ static const double secinm = 60 ;
377+ static const double secinh = secinm * 60 ;
378+ static const double secind = secinh * 24 ;
379+ static const double secinw = secind * 7 ;
380+ static const double secinM = secind * 30 ;
381+ static const double seciny = secind * 365 ;
382+ static const double secinD = seciny * 10 ;
383+
384+ const char * timein_s = (const char * ) sqlite3_value_text (argv [0 ]);
385+
386+ double timein ;
387+ if (sscanf (timein_s , "%lf" , & timein ) != 1 ) {
388+ sqlite3_result_error (context , "Bad size" , -1 );
389+ return ;
390+ }
391+
392+ const double ageinsec = time (NULL ) - timein ;
393+
394+ char returnagecat [32 ];
395+
396+ if (ageinsec < 0 ) {
397+ sqlite3_result_error (context , "Bad timestamp" , -1 );
398+ return ;
399+ }
400+ else if (ageinsec == 0 ) {
401+ sprintf (returnagecat , "%s" , "Zero" );
402+ }
403+ else if (ageinsec < secinm ) {
404+ sprintf (returnagecat , "%s" , "Secs" );
405+ }
406+ else if (ageinsec < secinh ) {
407+ sprintf (returnagecat , "%s" , "Mins" );
408+ }
409+ else if (ageinsec < secind ) {
410+ sprintf (returnagecat , "%s" , "Hrs" );
411+ }
412+ else if (ageinsec < secinw ) {
413+ sprintf (returnagecat , "%s" , "Days" );
414+ }
415+ else if (ageinsec < secinM ) {
416+ sprintf (returnagecat , "%s" , "Wks" );
417+ }
418+ else if (ageinsec < seciny ) {
419+ sprintf (returnagecat , "%s" , "Mos" );
420+ }
421+ else if (ageinsec < secinD ) {
422+ sprintf (returnagecat , "%s" , "Yrs" );
423+ }
424+ else {
425+ sprintf (returnagecat , "%s" , "Decs" );
426+ }
427+
428+ sqlite3_result_text (context , returnagecat , -1 , SQLITE_TRANSIENT );
429+ }
430+
431+ /*
432+ * Provides age from now from unix epoch time fields like mtime,
433+ * ctime, atime, crtime. Unit s (seconds), m (minutes), h (hours), d
434+ * (days), w (weeks), M (months), y (years), D (decades). (for use in
435+ * group by)
436+ *
437+ * Usage:
438+ * SELECT COUNT(*), epochtoage(time, unit) AS cat
439+ * FROM ..
440+ * GROUP BY cat;
441+ */
442+ static void epochtoage (sqlite3_context * context , int argc , sqlite3_value * * argv ) {
443+ (void ) argc ;
444+
445+ static const int64_t secins = 1 ;
446+ static const int64_t secinm = 60 ;
447+ static const int64_t secinh = secinm * 60 ;
448+ static const int64_t secind = secinh * 24 ;
449+ static const int64_t secinw = secind * 7 ;
450+ static const int64_t secinM = secind * 30 ;
451+ static const int64_t seciny = secind * 365 ;
452+ static const int64_t secinD = seciny * 10 ;
453+
454+ const char * timein_s = (const char * ) sqlite3_value_text (argv [0 ]);
455+ const char * unit_s = (const char * ) sqlite3_value_text (argv [1 ]);
456+
457+ double timein ;
458+ if (sscanf (timein_s , "%lf" , & timein ) != 1 ) {
459+ sqlite3_result_error (context , "Bad size" , -1 );
460+ return ;
461+ }
462+
463+ const int64_t ageinsec = time (NULL ) - timein ;
464+ if (ageinsec < 0 ) {
465+ sqlite3_result_error (context , "Bad timestamp" , -1 );
466+ return ;
467+ }
468+
469+ /* default to day */
470+ int64_t unit = 0 ;
471+ switch (* unit_s ) {
472+ case 's' :
473+ unit = secins ;
474+ break ;
475+ case 'm' :
476+ unit = secinm ;
477+ break ;
478+ case 'h' :
479+ unit = secinh ;
480+ break ;
481+ case 'd' :
482+ unit = secind ;
483+ break ;
484+ case 'w' :
485+ unit = secinw ;
486+ break ;
487+ case 'M' :
488+ unit = secinM ;
489+ break ;
490+ case 'y' :
491+ unit = seciny ;
492+ break ;
493+ case 'D' :
494+ unit = secinD ;
495+ break ;
496+ default :
497+ unit = secind ;
498+ break ;
499+ }
500+
501+ sqlite3_result_int64 (context , ageinsec / unit );
502+ }
503+
504+ /*
505+ * return the hostname running gufi_query
506+ *
507+ * Usage:
508+ * SELECT hostname();
509+ */
510+ static void hostname (sqlite3_context * context , int argc , sqlite3_value * * argv )
511+ {
512+ (void ) argc ; (void ) argv ;
513+
514+ char hostname [256 ] = "NOHOST" ;
515+ gethostname (hostname , sizeof (hostname ));
516+ hostname [255 ] = '\0' ; /* force terminate in case gethostname(2) errored */
517+
518+ sqlite3_result_text (context , hostname , -1 , SQLITE_TRANSIENT );
519+ }
520+
232521/* uint64_t goes up to E */
233522static const char SIZE [] = {'K' , 'M' , 'G' , 'T' , 'P' , 'E' };
234523
@@ -925,6 +1214,16 @@ int addqueryfuncs(sqlite3 *db) {
9251214 NULL , & sqlite3_strftime , NULL , NULL ) == SQLITE_OK ) &&
9261215 (sqlite3_create_function (db , "blocksize" , 2 , SQLITE_UTF8 ,
9271216 NULL , & blocksize , NULL , NULL ) == SQLITE_OK ) &&
1217+ (sqlite3_create_function (db , "intcat" , 1 , SQLITE_UTF8 ,
1218+ NULL , & intcat , NULL , NULL ) == SQLITE_OK ) &&
1219+ (sqlite3_create_function (db , "bytecat" , 1 , SQLITE_UTF8 ,
1220+ NULL , & bytecat , NULL , NULL ) == SQLITE_OK ) &&
1221+ (sqlite3_create_function (db , "agecat" , 1 , SQLITE_UTF8 ,
1222+ NULL , & agecat , NULL , NULL ) == SQLITE_OK ) &&
1223+ (sqlite3_create_function (db , "epochtoage" , 2 , SQLITE_UTF8 ,
1224+ NULL , & epochtoage , NULL , NULL ) == SQLITE_OK ) &&
1225+ (sqlite3_create_function (db , "hostname" , 0 , SQLITE_UTF8 ,
1226+ NULL , & hostname , NULL , NULL ) == SQLITE_OK ) &&
9281227 (sqlite3_create_function (db , "human_readable_size" , 1 , SQLITE_UTF8 ,
9291228 NULL , & human_readable_size , NULL , NULL ) == SQLITE_OK ) &&
9301229 (sqlite3_create_function (db , "basename" , 1 , SQLITE_UTF8 ,
0 commit comments